Spring IoC容器初始化源码(5)—prepareBeanFactory准备Bean工厂、回调BeanFactoryPostProcessor、注册BeanPostProcessor【两万字】

2022-09-23 10:06:36

  基于最新Spring 5.x,详细介绍了prepareBeanFactory配置BeanFactory、invokeBeanFactoryPostProcessors回调BeanFactoryPostProcessor扩展点、registerBeanPostProcessors注册BeanPostProcessor扩展点。

  上一篇文章:Spring IoC容器初始化源码(4)—<context:component-scan/>标签解析、spring.components扩展点、自定义Spring命名空间扩展点中,我们主要讲解了自定义命名空间和Spring5的spring.components这两个容器扩展点,以及< context:component-scan/>扩展标签的解析。
  现在我们继续向下学习refresh()方法,到此obtainFreshBeanFactory方法的大概内容算是结束了,我继续向下走,本篇文章的内容主要就是prepareBeanFactory配置BeanFactory、postProcessBeanFactory扩展BeanFactory、invokeBeanFactoryPostProcessors回调BeanFactoryPostProcessor扩展点、registerBeanPostProcessors注册BeanPostProcessor扩展点,以及MessageSource和Listener相关初始化

Spring IoC容器初始化源码 系列文章

Spring IoC容器初始化源码(1)—setConfigLocations设置容器配置信息

Spring IoC容器初始化源码(2)—prepareRefresh准备刷新、obtainFreshBeanFactory加载XML资源、解析<beans/>标签

Spring IoC容器初始化源码(3)—parseDefaultElement、parseCustomElement解析默认、扩展标签,registerBeanDefinition注册Bean定义

Spring IoC容器初始化源码(4)—<context:component-scan/>标签解析、spring.components扩展点、自定义Spring命名空间扩展点

Spring IoC容器初始化源码(5)—prepareBeanFactory、invokeBeanFactoryPostProcessors、registerBeanPostProcessors方法

Spring IoC容器初始化源码(6)—finishBeanFactoryInitialization实例化Bean的整体流程以及某些扩展点

Spring IoC容器初始化源码(7)—createBean实例化Bean的整体流程以及构造器自动注入

Spring IoC容器初始化源码(8)—populateBean、initializeBean实例化Bean以及其他依赖注入

< context:property-placeholder/>标签以及PropertySourcesPlaceholderConfigurer占位符解析器源码深度解析

三万字的ConfigurationClassPostProcessor配置类后处理器源码深度解析

基于JavaConfig的AnnotationConfigApplicationContext IoC容器初始化源码分析

1 prepareBeanFactory配置BeanFactory

在obtainFreshBeanFactory方法获取到新的BeanFactory之后,随即调用prepareBeanFactory方法对新获取的BeanFactory进行一系列配置。这也是applicationContext功能的扩展。
  配置的信息包括:

  1. 设置BeanFactory的类加载器,用于后面创建bean的实例。
  2. 设置SPEL表达式的解析器实例StandardBeanExpressionResolver,用于后面解析SPEL表达式。在后面的doCreateBean方法中我们会再次见到。
  3. 添加一个默认属性编辑器注册表实例ResourceEditorRegistrar,主要目的是后面调用其内部的registerCustomEditors方法注册一批常用的PropertyEditor,比如ResourceEditor。
  4. 添加一个BeanPostProcessor实例ApplicationContextAwareProcessor,主要目的是用于忽略一批Aware接口的setter方法的自动装配。由ApplicationContextAwareProcessor的后置处理方法中手动调用注入代替这些接口的setter自动注入。在后面的doCreateBean方法中我们会再次见到。
  5. 注册一批可以免配置默认自动注入的类型到resolvableDependencies缓存map中,可以直接获取该对应类型的属性的实例。包括BeanFactory、ResourceLoader、ApplicationEventPublisher、ApplicationContext。在后面的doCreateBean方法中我们会再次见到。
  6. 添加一个早期的后置处理器实例 ApplicationListenerDetector,专门用来探测监听器,并进行绑定。在后面的doCreateBean方法中我们会再次见到。
  7. 如果工厂中具有名为loadTimeWeaver名称的bean,则会注册一个LoadTimeWeaverAwareProcessor后置处理器到容器中。用于类加载期织入AspectJ用的。
  8. 手动注册一系列系统和JVM环境bean以及实例,environment、systemProperties、systemEnvironment。这就是所谓的手动注入
//------AbstractApplicationContext的相关属性/**
 * 类加载器,用于后面根据className创建bean的实例(如有必要)
 */@NullableprivateClassLoader beanClassLoader=ClassUtils.getDefaultClassLoader();/**
 * bean定义中SPEL表达式的解析器
 */@NullableprivateBeanExpressionResolver beanExpressionResolver;/**
 * 自定义的属性编辑器注册表
 */privatefinalSet<PropertyEditorRegistrar> propertyEditorRegistrars=newLinkedHashSet<>(4);/**
 * 按添加顺序先后排列的要使用BeanPostProcessor列表
 */privatefinalList<BeanPostProcessor> beanPostProcessors=newCopyOnWriteArrayList<>();/**
 * 要忽略自动注入的类型的列表
 */privatefinalSet<Class<?>> ignoredDependencyInterfaces=newHashSet<>();/**
 * 从依赖项类型映射到相应的自动注入的实例的map
 */privatefinalMap<Class<?>,Object> resolvableDependencies=newConcurrentHashMap<>(16);//---------ConfigurableApplicationContext接口的相关常量属性/**
 * 工厂中的 LoadTimeWeaver bean的名称。
 */String LOAD_TIME_WEAVER_BEAN_NAME="loadTimeWeaver";/**
 * 工厂中的 environment bean的名称。
 *
 * @since 3.1
 */String ENVIRONMENT_BEAN_NAME="environment";/**
 * 工厂中的 systemProperties bean的名称。
 * java.lang.System#getProperties()可以获取
 */String SYSTEM_PROPERTIES_BEAN_NAME="systemProperties";/**
 * 工厂中的 systemEnvironment bean的名称。
 * java.lang.System#getenv()可以获取
 */String SYSTEM_ENVIRONMENT_BEAN_NAME="systemEnvironment";/**
 * AbstractApplicationContext的方法
 * <p>
 * 配置工厂的标准上下文特征,例如上下文的 ClassLoader、一些BeanPostProcessor后处理器、手动注册一些的bean等等。
 * 这些特征都可以算作applicationContext功能的扩展
 *
 * @param beanFactory 要配置的BeanFactory
 */protectedvoidprepareBeanFactory(ConfigurableListableBeanFactory beanFactory){/*
     * 1 设置BeanFactory的类加载器,用于后面创建bean的实例
     * 直接使用上下文容器的类加载器,默认就是 Launcher$AppClassLoader 类加载器实例
     */
    beanFactory.setBeanClassLoader(getClassLoader());/*
     * 2 设置SPEL表达式的解析器实例StandardBeanExpressionResolver
     * 我们此前学习SPEL表达式的时候就说过,Spring默认使用StandardBeanExpressionResolver解析SPEL表达式#{}
     */
    beanFactory.setBeanExpressionResolver(newStandardBeanExpressionResolver(beanFactory.getBeanClassLoader()));/*
     * 3 添加一个默认属性编辑器注册表实例ResourceEditorRegistrar
     * 主要目的是调用其内部的registerCustomEditors方法注册一批常用的PropertyEditor,比如ResourceEditor
     *
     * PropertyEditor(属性编辑器)用于bean的属性注入时的类型自动转换,比如value字符串转换为各种集合,Resource资源类型等等
     * 我们可以实现PropertyEditorSupport接口自定义属性编辑器
     */
    beanFactory.addPropertyEditorRegistrar(newResourceEditorRegistrar(this,getEnvironment()));/*
     * 4 添加一个BeanPostProcessor实例ApplicationContextAwareProcessor
     *  BeanPostProcessor也是一个扩展回调接口,它的postProcessBeforeInitialization方法在bean的init-method执行之前执行
     *  它的postProcessAfterInitialization方法在bean的init-method执行之后执行
     *
     * ApplicationContextAwareProcessor的目的很简单,如果我们的bean实现了Aware标志性接口下的
     * EnvironmentAware、EmbeddedValueResolverAware、ResourceLoaderAware、ApplicationEventPublisherAware、MessageSourceAware、ApplicationContextAware六个接口
     * 那么在bean被初始化之后,init-method执行,将会由ApplicationContextAwareProcessor帮助我们调用相关接口的setter方法注入applicationContext或者embeddedValueResolver属性
     */
    beanFactory.addBeanPostProcessor(newApplicationContextAwareProcessor(this));/*
     * 5 忽略一批Aware接口的setter方法的自动装配
     *
     * 这一批接口就上面ApplicationContextAwareProcessor处理的手动装配的接口,由于上面的手动配装,因此不需要自动注入功能
     * 在此前的createBeanFactory方法中,就已经忽略了BeanNameAware、BeanFactoryAware、BeanClassLoaderAware接口的setter方法自动装配
     */
    beanFactory.ignoreDependencyInterface(EnvironmentAware.class);
    beanFactory.ignoreDependencyInterface(EmbeddedValueResolverAware.class);
    beanFactory.ignoreDependencyInterface(ResourceLoaderAware.class);
    beanFactory.ignoreDependencyInterface(ApplicationEventPublisherAware.class);
    beanFactory.ignoreDependencyInterface(MessageSourceAware.class);
    beanFactory.ignoreDependencyInterface(ApplicationContextAware.class);/*
     * 6 注册一批指定类型接口的默认自动注入实例
     *
     * 什么意思呢?一般我们的自动装配,都需要相关的注解、或者XML的配置自动注入
     *
     * 如果一个接口有多个实现,那么使用自动注入可能会报错
     * 使用该方法指定某个类型的接口,如果外部要注入该类型接口的对象,则会直接注入我们指定的对象
     *
     * BeanFactory、  -> 实际注入的是DefaultListableBeanFactory实例
     * ResourceLoader、ApplicationEventPublisher、ApplicationContext  ->实际注入的是当前上下文容器实例
     */
    beanFactory.registerResolvableDependency(BeanFactory.class, beanFactory);
    beanFactory.registerResolvableDependency(ResourceLoader.class,this);
    beanFactory.registerResolvableDependency(ApplicationEventPublisher.class,this);
    beanFactory.registerResolvableDependency(ApplicationContext.class,this);/*
     * 7 添加一个早期的后置处理器实例 ApplicationListenerDetector
     *
     * ApplicationListenerDetector是一个监听器探测器,专门用来探测监听器
     * 在bean实例化和依赖注入完毕之后,用于检测当前bean是不是ApplicationListener监听器的实现,是的话将它注册到应用的事件多播器上。
     */
    beanFactory.addBeanPostProcessor(newApplicationListenerDetector(this));/*
     * 8 如果工厂中具有名为loadTimeWeaver名称的bean,则会注册一个LoadTimeWeaverAwareProcessor后置处理器到容器中
     *
     * 说实话没研究过,看文章是啥类加载期织入AspectJ用的
     */if(beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)){
        beanFactory.addBeanPostProcessor(newLoadTimeWeaverAwareProcessor(beanFactory));// Set a temporary ClassLoader for type matching.//指定用于类型匹配的临时类加载器。 默认值为无,只需使用标准 bean 类加载器即可。
        beanFactory.setTempClassLoader(newContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));}/*
     * 9 手动注册一系列系统和JVM环境bean以及实例:
     * environment -> 容器环境变量对象,内部包含了systemEnvironment和systemProperties
     * systemProperties -> JVM环境变量对象,最开始的setConfigLocations部分我们就见过了
     * systemEnvironment -> 系统环境变量对象,最开始的setConfigLocations方法部分我们就见过了
     *
     * 调用registerSingleton,就是所谓的手动注册bean实例
     */if(!beanFactory.containsLocalBean(ENVIRONMENT_BEAN_NAME)){
        beanFactory.registerSingleton(ENVIRONMENT_BEAN_NAME,getEnvironment());}if(!beanFactory.containsLocalBean(SYSTEM_PROPERTIES_BEAN_NAME)){
        beanFactory.registerSingleton(SYSTEM_PROPERTIES_BEAN_NAME,getEnvironment().getSystemProperties());}if(!beanFactory.containsLocalBean(SYSTEM_ENVIRONMENT_BEAN_NAME)){
        beanFactory.registerSingleton(SYSTEM_ENVIRONMENT_BEAN_NAME,getEnvironment().getSystemEnvironment());}}

1.1 BeanPostProcessor后置处理器扩展点

BeanPostProcessor是Spring提供的一个扩展接口,Spring中大部分功能都是通过后处理器的方式进行扩展的。这也是ApplicationContext容器相比于BeanFactory的改进,使用BeanFactory时,BeanPostProcessor需要手动调用方法注册,而使用ApplicationContext时,BeanPostProcessor可以通过< bean/>标签自动注册。

  它提供了两个方法,Spring5之后由抽象方法改为默认方法:

  1. postProcessBeforeInitialization:bean实例化以及依赖注入完毕之后,initMethod方法调用完毕之前调用。
  2. postProcessAfterInitialization:bean实例化以及依赖注入完毕之后,initMethod方法调用完毕之后调用。
  3. 注意,BeanPostProcessor仅仅是一个超级接口,我们后面还会看到更多的后置处理器的子接口和实现,它们还拥有其他自己方法,它们也可能会在其他阶段被调用,而不仅仅是上面的两个方法和阶段。
/**
 * Spring提供的扩展接口
 */publicinterfaceBeanPostProcessor{/**
     * bean实例化以及依赖注入完毕之后,initMethod方法调用完毕之前调用
     *
     * @param bean     初始化的bean实例
     * @param beanName beanName
     * @return 后续要使用的 bean 实例,如果为null,则不会调用后续的后置处理器对应的方法,一般还是返回bean
     */@NullabledefaultObjectpostProcessBeforeInitialization(Object bean,String beanName)throwsBeansException{//默认返回beanreturn bean;}/**
     *bean实例化以及依赖注入完毕之后,initMethod方法啊调用完毕之后调用
     *
     * @param bean     初始化的bean实例
     * @param beanName beanName
     * @return 后续要使用的 bean 实例,如果为null,则不会调用后续的后置处理器对应的方法,一般还是返回bean
     */@NullabledefaultObjectpostProcessAfterInitialization(Object bean,String beanName)throwsBeansException{//默认返回beanreturn bean;}}

1.1.1 使用案例

我们只需要实现BeanPostProcessor接口然后将其当作普通bean注册到Spring容器中,在bean实例化的过程中就会自动顺序调用所有BeanPostProcessor实例的相关回调方法。如果要指定顺序,那么增加实现org.springframework.core.Ordered接口即可。

  测试类:

publicclassBeanPostProcessorTest{privateString string;publicBeanPostProcessorTest(){System.out.println("无参构造器调用");}publicBeanPostProcessorTest(String string){System.out.println("带参构造器调用");this.string= string;}publicvoidsetString(String string){System.out.println("setter调用");this.string= string;}publicvoidinit(){System.out.println("+++++++++++++++ init-method +++++++++++++++++++");}@OverridepublicStringtoString(){return"BeanPostProcessorTest{"+"string='"+ string+'\''+'}';}}

  自定义的后置处理器:

publicclassMyBeanPostProcessor{publicstaticclassMyBeanPostProcessor1implementsBeanPostProcessor,Ordered{@OverridepublicObjectpostProcessBeforeInitialization(Object bean,String beanName)throwsBeansException{System.out.println("-------------postProcessBeforeInitialization1 start-------------");System.out.println("bean: "+ bean);System.out.println("beanName: "+ beanName);//如果返回null,则不会调用后续的后置处理器对应的方法System.out.println("-------------postProcessBeforeInitialization1 end-------------");return bean;}@OverridepublicObjectpostProcessAfterInitialization(Object bean,String beanName)throwsBeansException{System.out.println("-------------postProcessAfterInitialization1 start-------------");System.out.println("bean: "+ bean);System.out.println("beanName: "+ beanName);System.out.println("-------------postProcessAfterInitialization1 end-------------");return bean;}/**
         * @return 返回值越小,执行优先级越高
         */@OverridepublicintgetOrder(){return0;}}publicstaticclassMyBeanPostProcessor2implementsBeanPostProcessor,Ordered{@OverridepublicObjectpostProcessBeforeInitialization(Object bean,String beanName)throwsBeansException{System.out.println("-------------postProcessBeforeInitialization2 start-------------");System.out.println("bean: "+ bean);System.out.println("beanName: "+ beanName);System.out.println("-------------postProcessBeforeInitialization2 end-------------");return bean;}@OverridepublicObjectpostProcessAfterInitialization(Object bean,String beanName)throwsBeansException{System.out.println("-------------postProcessAfterInitialization2 start-------------");System.out.println("bean: "+ bean);System.out.println("beanName: "+ beanName);System.out.println("-------------postProcessAfterInitialization2 end-------------");return bean;}/**
         * @return 返回值越小,执行优先级越高
         */@OverridepublicintgetOrder(){return2;}}}

  配置文件:

<!--注册自定义的后置处理器--><beanclass="com.spring.source.MyBeanPostProcessor.MyBeanPostProcessor1"id="myBeanPostProcessor1"/><beanclass="com.spring.source.MyBeanPostProcessor.MyBeanPostProcessor2"id="myBeanPostProcessor2"/><!--注册bean--><beanclass="com.spring.source.BeanPostProcessorTest"id="beanPostProcessorTest"init-method="init"><propertyname="string"value="str1"/></bean>

  测试:

@TestpublicvoidbeanPostProcessorTest(){ClassPathXmlApplicationContext ac=newClassPathXmlApplicationContext("spring-config-test.xml");//手动注入,不会触发BeanPostProcessor回调
    ac.getBeanFactory().registerSingleton("beanPostProcessorTest2",newBeanPostProcessorTest("registerSingleton"));}

结果如下:

无参构造器调用
setter调用-------------postProcessBeforeInitialization1 start-------------
bean:BeanPostProcessorTest{string='str1'}
beanName: beanPostProcessorTest-------------postProcessBeforeInitialization1 end--------------------------postProcessBeforeInitialization2 start-------------
bean:BeanPostProcessorTest{string='str1'}
beanName: beanPostProcessorTest-------------postProcessBeforeInitialization2 end-------------+++++++++++++++ init-method+++++++++++++++++++-------------postProcessAfterInitialization1 start-------------
bean:BeanPostProcessorTest{string='str1'}
beanName: beanPostProcessorTest-------------postProcessAfterInitialization1 end--------------------------postProcessAfterInitialization2 start-------------
bean:BeanPostProcessorTest{string='str1'}
beanName: beanPostProcessorTest-------------postProcessAfterInitialization2 end-------------
带参构造器调用

单纯的使用的话,还是比较简单的!

1.1.2 ApplicationContextAwareProcessor

  ApplicationContextAwareProcessor实现了BeanPostProcessor后置处理器接口,是Spring自带的后置处理器。用于向实现了Aware接口的子接口EnvironmentAware、EmbeddedValueResolverAware、ResourceLoaderAware、ApplicationEventPublisherAware、MessageSourceAware、ApplicationContextAwarebean的bean中注入相应的属性。
这里的注入就是:先判断属于某个类型,然后转换换为该类型,并调用相关方法。

/**
 * Spring提供的后置处理器接口的实现
 * <p>
 * 用于向实现了Aware接口的子接口EnvironmentAware、EmbeddedValueResolverAware、ResourceLoaderAware、
 * ApplicationEventPublisherAware、MessageSourceAware、ApplicationContextAwarebean的bean中注入相应的属性。
 */classApplicationContextAwareProcessorimplementsBeanPostProcessor{privatefinalConfigurableApplicationContext applicationContext;privatefinalStringValueResolver embeddedValueResolver;
  • 作者:刘Java
  • 原文链接:https://blog.csdn.net/weixin_43767015/article/details/109304866
    更新时间:2022-09-23 10:06:36