目录
后置处理器PostProcessor
PostProcessor的种类
Aware
事件监听模式
Spring容器的刷新逻辑
ApplicationContext refresh的流程概述
1---prepareRefresh
2---obtainFreshBeanFactory
3---prepareBeanFactory
4---postProcessBeanFactory
5---invokeBeanFactoryPostProcessors
6---registerBeanPostProcessors
7---initMessageSource
8---initApplicationEventMulticaster
9---onRefresh
10---registerListeners
11---finishBeanFactoryInitialization
12---finishRefresh
小结
-
后置处理器PostProcessor
- 本身也是一种需要注册到容器里的Bean
- 其里面的方法会在特定的时机被容器调用
- 实现不改变容器或者Bean核心逻辑的情况下对Bean进行扩展
- 对Bean进行包装,影响其行为、修改Bean的内容等
-
PostProcessor的种类
- 大类分为容器级别的后置处理器以及Bean级别的后置处理器
- BeanDefinitionRegistryPostProcessor
- BeanFactoryPostProcessor
- BeanPostProcessor
- 前两个是容器级别的处理器,最后一个是Bean级别的处理器
- BeanDefinitionRegistryPostProcessor:
- 负责自定义的BeanDefinition的注册;允许在正常的BeanFactoryPostProcessor检测开始之前注册更多的自定义beanDefinition
- 继承BeanFactoryPostProcessor,可以看成是一种特殊的BeanFactoryPostProcessor;他只有一个方法
- 方法展示:
- 创建BeanDefinition实例,再将其注册到形参register里面
- 编写实现类;要先将其实现类注入到容器里,才能和容器对话
- main函数中获得我们刚注册的bean实例
- BeanFactoryPostProcessor:影响容器的行为
- BeanPostProcessor:
- 对于每个由容器创建的bean实例,BeanPostProcessor都会在调用容器初始化之前以及在任何bean初始化回调之后,都从容器获得回调执行;注意不是BeanDefinition实例
- 方法展示:
- 在main函数执行发现每一个Spring管理的bean都会去执行那两个方法,且先执行before再after
- 可以使用BeanPostProcessor的能力对bean进行包装即在bean创建之后在postProcessAfterInitialization对bean包装统一的逻辑,比如耗时统计的日志记录,之后再返回增强的bean
- 在源码中在逐个执行排序好的postprocessors时,采用责任链模式来执行,每个接收者都包含对另外一个接收者的引用;如果一个对象不能处理该请求,会把该对象转发给下一个接收者,以此类推
-
Aware
- 容器对bean本身的逻辑是无侵入的,因此bean不需要了解容器的状态可直接使用容器
- 但在某些情况下需要在bean中对容器进行直接操作的,这时就需要在bean中设置对容器的感知了,这便是Aware接口的作用
- 这个接口里面什么方法都没有,所以只能当作标签来使用
- ApplicationContextAware
- 在容器创建这个bean实例的时候,将容器本身的实例作为参数传进来给这个bean来使用
- BeanFactoryAware:获取当前的BeanFactory,这样就可以调用容器的服务
- ApplicationEventPublisherAware:获取发布器实例已发布的事件
- 想实现什么功能就调用相关接口
- 例:获取注册到这个容器里的所有beandefinition的name
- main函数
- 注意:想要获取容器提供的资源,除了继承Aware接口之外,类本身还是要被Spring容器管理的bean才行
-
事件监听模式
- 回调函数
- 往组件注册自定义的方法以便组件在特定场景下调用
- Thread类就是组件,run()方法就是回调函数,我们并不希望直接调用Runnable里面的run方法
- 而是希望Thread组件在某个时刻去执行它,该时刻就是在调用start方法之后再去执行
-
事件监听器模式
- 监听器将监听感兴趣的事件,一旦事件发生,便做出响应
- 事件源( Event Source ):比如说一个按钮,要想使某个按钮对某个事件做出响应,就需要监听器
- 事件监听器( Event Listener ):需要注册到事件源上才能被调用,主要用来监听事件并进行事件处理或者转发
- 事件对象( Event Object ):负责事件源和事件监听器之间的信息传递
- 例子:
- 1---创建事件
- 2---创建事件监听器
- 实现类
- 3---创建事件源
- 因为需要将事件监听器注册到事件源里,事件监听器有多个,所以需要定义一个List集合
- 提供一个共有的方法供外界输入数据,还有输出数据即发布事件的方法
- 主要发布给listener,遍历所有的listener,都发一个事件,listener再去处理事件
- 还需要将lisener注册到事件源里面,注册好之后,事件源去发布事件,交给事件监听器去处理
- 使用事件监听器模式可以解耦,事件监听器和事件源是可以分开开发的
- 其中只有事件作为联系,不用关心另一方怎么实现的,事件监听器其实是观察者模式的一种实现
- 事件源组件和事件等于观察者的主题主键类似,事件监听器对标观察者模式的观察者
-
Spring的事件驱动模型
- 事件驱动模型的三大组成部分
- (一)事件:ApplicatinEvent抽象类
- 继承自jdk的EventObject,所有事件将继承于ApplicatinEvent,并通过里面的source成员变量获得事件
- 事件源就是发布事件的地方,这里指的就是容器本身
- ApplicationEvent并不单单指的是容器事件,为了专门给容器定制事件,产生了ApplicationContextEvent子类,用来表示容器事件
- 下面是框架对其的实现类
- 在容器中发布一个任意类型的事件之后,会被自动封装为PayloadApplicationEvent类
- (二)事件监听器 : ApplicationListener
- 用户可以实现此接口,实现里面的方法实现自定义监听器;也可以使用注解的方式对类进行监听
- 这样就可以将该类晋升为监听器,同时使用sayHello方法进行监听
- SmartApplicationListener
- 继承order,可以给事件排序
- 判断事件类型和事件源类型是否和当前监听者匹配,这样监听者就可以筛选自己感兴趣的事件或者事件源
- GenericApplicationListener
- ResolvableType:获取泛型信息的工具,可以通过它获得泛型的任何信息类似于反射
- (三)事件发布器 : Publisher以及Multicaster
- 可以在bean里面通过Aware获得ApplicationEvnetPublisher实例,其实也就是获得容器这个实例
- 就可以发布自定义的事件给容器里注册的自定义的eventListener去处理
- 发现容器ApplicationContext继承ApplicationEventPublisher
- ApplicationEventPublisher
- 它里面的两个方法都是用来发布事件的,即这个接口只能用来发布事件
- ApplicationEventMulticaster
- 有添加和删除listener、发布的功能
- Executor:执行器,说明它支持多线程去处理监听器的方法
- 为什么需要ApplicationEventPublisher和ApplicationEventMulticaster这两个接口?
- 既然ApplicationEventMulticaster已经具有了所有的功能,为什么不直接使用它替代掉ApplicationEventPublisher?
- 比如说像bean容器本身(applicationcontext)就只想发布事件,而不想维护事件监听器这些
- 所以Spring将事件源做了进一步分割,抽象出事件发布器接口,将ApplicationEventMulticaster作为代理
- 就像applicationcontext用我们的DefaultListableFactory作为代理一样,让ApplicationEventPublisher的实现类来实现publishEvent里面的逻辑
- 那ApplicationEventPublisher里面就主要实现调用ApplicationEventMulticaster实现类的multicastEvent来发布事件就可以了
-
Spring容器的刷新逻辑
- 刷新的意思就是将BeanFactory清空为初始状态,然后再按照程序意图填满各种bean实例
- 注解的beanDefinition注册时,DefaultListableBeanFactory这个实例已经在注册主键类之前,也就是调用容器的构造函数时就已经创建了
- 后置器ApplicationContextAwareProcessor:当bean实例继承ApplicationContextAware接口时,去给这些bean实例注入ApplicationContext对象
- 调用完了容器级别的后置处理器之后,接下来就是bean级别的后置处理器
- register这一步就是将先前定义的bean级别的后置处理器给注册到容器里,方便后续在调用getBean方法去创建bean实例时,在特定的环节去触发这些后置处理器执行一些特定的逻辑,比如AOP织入
- 初始化事件发布器:用来接收实现ApplicationEventPublisher接口类发送过来的不同的事件,并派给不同的事件监听者进行处理
- onRefresh():钩子方法,用于初始化其他特殊的bean,发生在单例的bean初始化之前去执行
- 往先前已经初始化出来的ApplicationEventMulticaster去注册相关的监听器,用来监听不同的事件
-
ApplicationContext refresh的流程概述
- ApplicationContext是Spring中的核心容器,refresh是ApplicationContext的一个方法,主要作用是用来初始化ApplicationContext
- refresh一共分为十二个步骤
- 所有的ApplicationContext有一个共同的父类叫AbstractApplicationContext
- 这个父类里有refresh方法,这个方法里面有12个比较重要的方法
- (1)蓝色:代表做一些准备工作
- (2—6)绿色:创建并准备BeanFactory对象
- 为什么需要BeanFactory对象呢?
- 因为ApplicationContext只是一个外部容器,核心功能还需要交给BeanFactory来完成(Bean的创建、Bean的依赖注入、Bean的初始化)
- (7—12)黄色:准备ApplicationContext,为ApplicationContext里面一些特有的功能做一些准备
- (11)红色:比较重要,是在创建和初始化单例对象;容器当中的单例对象都是在第11步创建并初始化完成的
-
1---prepareRefresh
- 要点
- 这一步创建和准备了Environment对象
- 要理解Environment对象的作用
- prepareRefresh主要就是准备了一个Environment对象,这个环境对象后续的代码里都会用到
- 他就是为Spring后续运行时提供一些键值信息
- systemProperties:java中的一些键值(java中的默认编码、文件分割符等)
- systemEnvironment:提供了操作系统的键值对(java_home、path、classPath等)
- 自定义:从自定义的properties文件当中的读取到的信息;例如application.properties文件
- 即Environment的作用就是管理各种键值信息,将来其他地方可以用到这些信息,例如@Value
-
2---obtainFreshBeanFactory
- 作用:初始化beanFactory,加载并解析配置
- 方法中做了二件事:
- refreshBeanFactory():创建beanFactory、指定序列化Id、定制beanFactory、加载bean定义
- getBeanFactory():返回beanFactory实例
- refreshBeanFactory()方法主要执行:
- 如果有bean工厂,销毁bean以及关闭bean工厂
- createBeanFactory():创建beanFactory
- beanFactory.setSerializationId(getId()):指定序列化Id
- customizeBeanFactory():定制BeanFactory
- loadBeanDefinitions():加载bean定义
-
3---prepareBeanFactory
- 作用:配置工厂的标准上下文特征,为beanFactory设置类加载器、后置处理器等
- 方法逻辑梳理如下:
- 设置类加载器,默认是RestartClassLoader;
- 设置表达式解析器StandardBeanExpressionResolver,比如SPEL语法就是该解析器内维护的SpelExpressionParser进行处理的;
- 向Set<PropertyEditorRegistrar> propertyEditorRegistrars 添加 ResourceEditorRegistrar;
- 注册beanPostProcessor如ApplicationContextAwareProcessor;
- 向Set<Class<?>> ignoredDependencyInterfaces中添加对象如EnvironmentAware、EmbeddedValueResolverAware、ResourceLoaderAware、ApplicationEventPublisherAware、MessageSourceAware、ApplicationContextAware;也就是说这些类将不会通过Autowired自动注入而是会被BeanFactory通过比BeanFactoryAware或者ApplicationContext通过ApplicationContextAware这种方式设置
- 向Map<Class<?>, Object> resolvableDependencies放入BeanFactory、ResourceLoader、ApplicationEventPublisher、ApplicationContext;表示是已经解析的依赖可以直接使用
- 注册应用监听器检测器,如果实例化bean是ApplicationListener,则其将会被放入applicationListeners;
- 如果 loadTimeWeaver 存在于beanFactory,则注册LoadTimeWeaverAwareProcessor并设置TempClassLoader为ContextTypeMatchClassLoader
- 注册默认的环境信息bean如environment、systemProperties、systemEnvironment
-
4---postProcessBeanFactory
- Spring中并没有具体去实现postProcessBeanFactory方法,是提供给想要实现BeanPostProcessor的三方框架使用的
- 谁要使用谁就去实现
- 作用是在BeanFactory准备工作完成后做一些定制化的处理,一般结合BeanPostProcessor接口的实现类一起使用,注入一些重要资源(类似Application的属性和ServletContext的属性)
- 最后需要设置忽略这类BeanPostProcessor子接口的自动装配
- 是一种模板方法的设计模式,refresh方法的主要脉络都被父类给规定死了,但是有一些可以扩展的方法把它留空,将来有子类去实现
-
5---invokeBeanFactoryPostProcessors
- 主要用来调用beanFactory后置处理器来修改beanDefinition
- 该方法实例化并调用已经注册到beanFactory的beanFactoryPostProcessor实例
- BeanFactory有两个扩展点,第一处就是交给子类去扩展,第二处就是交给bean的后置处理器
-
6---registerBeanPostProcessors
- 本方法会注册所有的 BeanPostProcessor,将所有实现了 BeanPostProcessor 接口的类加载到 BeanFactory 中
- BeanPostProcessor 接口是 Spring 初始化 bean 时对外暴露的扩展点,Spring IoC 容器允许 BeanPostProcessor 在容器初始化 bean 的前后,添加自己的逻辑处理
- 在 registerBeanPostProcessors 方法只是注册到 BeanFactory 中,具体调用是在 bean 初始化的时候
- 具体的:在所有 bean 实例化时,执行初始化方法前会调用所有 BeanPostProcessor 的 postProcessBeforeInitialization 方法,在执行初始化方法后会调用所有 BeanPostProcessor 的 postProcessAfterInitialization 方法
-
7---initMessageSource
- 主要用于国际化,说简单点就是不同语言之间的翻译
- 该方法将会初始化MessageSource并尝试设置parentMessageSource,然后作为单例bean注册到容器中
- 通常注册是 DelegatingMessageSource 实例
-
8---initApplicationEventMulticaster
- 该方法主要完成事件管理类的初始化,并加入一级缓存
- 初始化ApplicationEventMulticaster事件,默认使用SimpleApplicationEventMulticaster事件
-
9---onRefresh
- onRefresh()方法是Spring预留给子类,用于初始化其他的Bean用的
- 例:Spring中 AbstractApplicationContext onRefresh()的是没有做任何事情的
- 而在Spring Boot中 ServletWebServerApplicationContext onRefresh()是有重写这个方法的
- 其中super.onRefresh()为GenericWebApplicationContext onRefresh()
- 这一步是初始化主题功能
-
10---registerListeners
- 方法主要将实现监听器接口(即ApplicationListener接口)的bean们注册到多播器中,即存储到applicationListenerBeans集合中
- 代码分为三个步骤:
- 1.注册硬编码方式的监听器
- 2.注册配置文件的监听器
- 3.发布需要进行发布的事件
-
11---finishBeanFactoryInitialization
- 该方法会实例化所有剩余的非懒加载单例 bean
- 除了一些内部的 bean、实现了 BeanFactoryPostProcessor 接口的 bean、实现了 BeanPostProcessor 接口的 bean,其他的非懒加载单例 bean 都会在这个方法中被实例化,并且 BeanPostProcessor 的触发也是在这个方法中
- 代码步骤:
- 1.初始化此上下文的转换服务
- 2.如果beanFactory之前没有注册嵌入值解析器,则注册默认的嵌入值解析器:主要用于注解属性值的解析
- 3.初始化LoadTimeWeaverAware Bean实例对象
- 4.冻结所有bean定义,注册的bean定义不会被修改或进一步后处理,因为马上要创建 Bean 实例对象了
- 5.实例化所有剩余(非懒加载)单例对象
-
12---finishRefresh
- 完成上下文的刷新工作,包括初始化LifecycleProcessor,发布刷新完成事件等
- 方法功能梳理:
- 清理前面记录的类资源(因为已经有了BeanDefinition)
- 初始化生命周期处理器,默认是DefaultLifecycleProcessor,并作为单例注册到容器
- 触发DefaultLifecycleProcessor的onRefresh方法,简单来讲就是触发那些实现了Lifecycle的bean的start方法并将running状态设置为true
- 发布事件ContextRefreshedEvent,标志着上下文刷新执行完毕
- 注册ApplicationContext到LiveBeansView内部的applicationContexts中
- 启动webserver,处理webserver的service与connector,并触发connector的start方法
- 发布ServletWebServerInitializedEvent事件,标志着WebServer启动完毕
-
小结
- 1.prepareRefresh---做好准备工作(创建Environment对象,为Spring后续的运行提供一些键值信息)
- 2.obtainFreshBeanFactory ---创建或获取BeanFactory
- 3.prepareBeanFactory ---准备BeanFactory(为BeanFactory创建各个成员变量,EL表达式解析器、类型转换器、内置的BeanPostProcessor)
- 4.postProcessBeanFactory ---子类扩展BeanFactory
- 5.invokeBeanFactoryPostProcessors ---后处理器扩展BeanFactory(Bean工厂的后置处理器:ConfigurationClassPostProceessors,解析配置类的注解:@Configuration、@Bean等)
- 6.registerBeanPostProcessors ---准备Bean后处理器(常见的有三个,一个是解析@Autwired注解,一个是解析@Resource、一个是解析@Aspect,创建代理类的)
- 7.initMessageSource ---为ApplicationContext提供国际化功能
- 8.initApplicationEventMulticaster ---为ApplicationContext提供事件发布器
- 9.onRefresh ---留给子类扩展
- 10.registerListeners ---为ApplicationContext准备监听器
- 11.finishBeanFactoryInitialization ---初始化单例Bean,执行Bean后处理器扩展
- 12.finishRefresh ---准备生命周期管理器,发布ContextRefreshed事件