2.3 spring5源码系列---内置的后置处理器PostProcess加载源码

前端之家收集整理的这篇文章主要介绍了2.3 spring5源码系列---内置的后置处理器PostProcess加载源码前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。

本文涉及主题

1. beanfactoryPostProcessor调用过程源码剖析

2. 配置类的解析过程源码

3. 配置类@Configuration加与不加的区别

4. 重复beanName的覆盖规则

5. @ComponentScan的解析原理

 


 

一. 研究目标: 解析spring如何加载配置类

我们经常会在一个类上打上@Configuration,@Component,@Bean等. 带有这些注解的类,就是我们所说的配置类. 那么,spring启动的时候,是如何加载这些配置类的呢?

下面就以此为目的,分析spring源码. 本节的内容是对上一节内容的实战分析,同时更加详细的解读spring源码

 

 

我们知道,spring启动的时候做了3件事,就是上面的三件事. 

第一件事: 调用this()自身的无参构造函数. 初始化了BeanDefinitionReader和BeanDefinitionScanner,同时初始化了很多spring的原始后置处理器,这些处理器是用来加载bean的

第二件事: 调用register(..) 注册配置类

第三件事: refresh(..) 这里包含了整个ioc创建bean的全生命周期, 今天重点看invokebeanfactoryPostProcessors(beanfactory)加载配置类

 

二. 准备工作: 自定义配置类MainConfig

我们先定义好要分析加载的配置类

package com.lxl.www.iocbeanlifecicle;

import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;

/**
 * 这是一个配置类,* 在配置类里面定义了扫描的包路径com.lxl.www.iocbeanlifecicle
 * 这是会将这个包下配置了注解的类扫描到ioc容器里面,成为一个成熟的bean
 */
@Configuration
@ComponentScan(basePackages = {"com.lxl.www.iocbeanlifecicle"})
public class MainConfig {
}

 

这个配置类很简单,使用@ComponentScan注解指定了扫描的包. @Configuration指定当前是一个配置类

接下来定义一个main方法,加载配置类.

 package com.lxl.www.iocbeanlifecicle;


import org.springframework.context.annotation.AnnotationConfigApplicationContext;

 MainStarter {
    static void main(String[] args) {
        // 第一步: 通过AnnotationConfigApplicationContext读取一个配置类
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(MainConfig.);
        context.addbeanfactoryPostProcessor();
        Car car = (Car) context.getBean(car");
        System.out.println(car.getName());
        context.close();
    }
}

 

在main里,通过AnnotationConfigurationApplicationContext读取配置类MainConfig.class.

配置类被传进来以后,到底是怎么被解析的呢? 这就是我们分析的线索

始终不要忘记我们的整体架构图. 对照这个图来分析. 思路更清晰. 整体内容讲解在这里: https://www.cnblogs.com/ITPower/p/13677635.html

 

 

下面,从入口进入. 我们的入口就是这里

new AnnotationConfigApplicationContext(MainConfig.class);

 

下面进入AnnotationConfigApplicationContext的构造方法

public AnnotationConfigApplicationContext(Class<?>... componentClasses) {
         进入构造函数,首先调用自身的构造方法this();
         调用自身的构造方法之前,要先调用父类的构造方法
        this();
         register配置注册
        register(componentClasses);
         ioc容器shua新接口--非常重要
        refresh();
    }

 

三、读取配置类后置处理器ConfigurationClassPostProcessor

3.1 调用this()无参构造函数

public AnnotationConfigApplicationContext() {
        *
         * 创建了一个Bean定义的读取器.
         * 完成了spring内部BeanDefinition的注册(主要是后置处理器)
         * 读取了很多spring自定义的配置(主要是后置处理器). 这些类都是spring 的原始类(也就是创世纪的类).
         */
        this.reader = new AnnotatedBeanDefinitionReader();

        *
         * 创建BeanDefinition扫描器
         * 可以用来扫描包或者类,进而转换为bd
         *
         * Spring默认的扫描包不是这个scanner对象
         * 而是自己new的一个ClassPathBeanDefinitionScanner
         * Spring在执行工程后置处理器ConfigurationClassPostProcessor时,去扫描包时会new一个ClassPathBeanDefinitionScanner
         *
         * 这里的scanner仅仅是为了程序员可以手动调用AnnotationConfigApplicationContext对象的scan方法
         * 通过调用context.scan("package name");扫描处理配置类
         * 扫描
         */
        this.scanner = new ClassPathBeanDefinitionScanner(this);
    }

 

在初始化AnnotatedBeanDefinitionReader(this);的时候,注册了很多后置处理器

*
     * Register all relevant annotation post processors in the given registry.
     * @param registry the registry to operate on
     * @param source the configuration source element (already extracted)
     * that this registration was triggered from. May be {@code null}.
     * @return a Set of BeanDefinitionHolders,containing all bean definitions
     * that have actually been registered by this call
     */
    static Set<BeanDefinitionHolder> registerAnnotationConfigProcessors(
            BeanDefinitionRegistry registry,@Nullable Object source) {

         获取beanfactory
        DefaultListablebeanfactory beanfactory = unwrapDefaultListablebeanfactory(registry);
        *
         * 判断beanfactory中是否有AnnotationAwareOrderComparator和ContextAnnotationAutowireCandidateResolver
         * 没有则添加
         if (beanfactory != null) {
            if (!(beanfactory.getDependencyComparator() instanceof AnnotationAwareOrderComparator)) {
                beanfactory.setDependencyComparator(AnnotationAwareOrderComparator.INSTANCE);
            }
            if (!(beanfactory.getAutowireCandidateResolver() instanceof ContextAnnotationAutowireCandidateResolver)) {
                beanfactory.setAutowireCandidateResolver(new ContextAnnotationAutowireCandidateResolver());
            }
        }

         BeanDefinitionHolder: 为BeanDefinition设置名字和别名
        Set<BeanDefinitionHolder> beanDefs = new LinkedHashSet<>(8);

         如果registry中没有ConfigurationClassPostProcessor配置类后置处理器,就添加一个
        if (!registry.containsBeanDefinition(CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME)) {
            RootBeanDefinition def = new RootBeanDefinition(ConfigurationClassPostProcessor.class);
            def.setSource(source);
             构建BeanDefinitionHolder,并添加到beanDefs
            beanDefs.add(registerPostProcessor(registry,def,CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME));
        }

         如果rigistry中,没有AutowiredAnnotationBeanPostProcessor  Autowired注解bean的后置处理器,则添加一个
        registry.containsBeanDefinition(AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME)) {
            RootBeanDefinition def = new RootBeanDefinition(AutowiredAnnotationBeanPostProcessor.class);
            def.setSource(source);
             Check for JSR-250 support,and if present add the CommonAnnotationBeanPostProcessor.
         检查对JSR-250的支持,如果rigistry中没有 CommonAnnotationBeanPostProcessor 通用注解后置处理器,1)">if (jsr250Present && !registry.containsBeanDefinition(COMMON_ANNOTATION_PROCESSOR_BEAN_NAME)) {
            RootBeanDefinition def = new RootBeanDefinition(CommonAnnotationBeanPostProcessor. Check for JPA support,and if present add the PersistenceAnnotationBeanPostProcessor.
         检查对jpa的支持,如果不包含 internalPersistenceAnnotationProcessor,持久化注解处理器,就添加一个
        if (jpaPresent && !registry.containsBeanDefinition(PERSISTENCE_ANNOTATION_PROCESSOR_BEAN_NAME)) {
            RootBeanDefinition def =  RootBeanDefinition();
            try {
                def.setBeanClass(ClassUtils.forName(PERSISTENCE_ANNOTATION_PROCESSOR_CLASS_NAME,AnnotationConfigUtils..getClassLoader()));
            }
            catch (ClassNotFoundException ex) {
                throw  IllegalStateException(
                        Cannot load optional framework class: " + PERSISTENCE_ANNOTATION_PROCESSOR_CLASS_NAME,ex);
            }
            def.setSource(source);
            beanDefs.add(registerPostProcessor(registry,PERSISTENCE_ANNOTATION_PROCESSOR_BEAN_NAME));
        }

         检查对事件监听的支持,如果不包含事件监听处理器 internalEventListenerProcessor,1)">registry.containsBeanDefinition(EVENT_LISTENER_PROCESSOR_BEAN_NAME)) {
            RootBeanDefinition def = new RootBeanDefinition(EventListenerMethodProcessor.);
            def.setSource(source);
            beanDefs.add(registerPostProcessor(registry,EVENT_LISTENER_PROCESSOR_BEAN_NAME));
        }

         如果不包含事件监听工厂处理器 internalEventListenerFactory,1)">registry.containsBeanDefinition(EVENT_LISTENER_FACTORY_BEAN_NAME)) {
            RootBeanDefinition def = new RootBeanDefinition(DefaultEventListenerFactory.return beanDefs;
    }

 

我们看到,注册了6个原始RootBeanDefinition,这些bean是spring自己提前定义好的,他们的加载是整个spring的基础. 用于解析spring中其他的类

而这一次我们要研究配置类是如何被读取的,所以重点关注的是下面这个后置处理器

ConfigurationClassPostProcessor.class

 

这里还有很多其他的原始类被注册了,但我们的目标是分析配置类是如何被读取的,所以,其他的先忽略,只看ConfigurationClassPostProcessor.

3.2 ConfigurationClassPostProcessor的继承结构

 

 可以看到ConfigurationClassPostProcessor是同时实现了BeanDefinitionRegistryPostProcessor和beanfactoryPostProcessor. 这一点我们需要记住,后面会使用到

 

2.3 ConfigurationClassPostProcessor是如何被注册

添加一个
        registry.containsBeanDefinition(CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME)) {
            RootBeanDefinition def = new RootBeanDefinition(ConfigurationClassPostProcessor.);
            def.setSource(source);
                        beanDefs.add(registerPostProcessor(registry,CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME));
        }

 

首先,构建了一个RootBeanDefinition. 然后调用registerPostProcessor方法,三个入参分别是

registry: BeanDefinitionRegistry注册器,用于注册BeanDefinition
def: 刚刚构建的RootBeanDefinition
CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME: 构建BeanDefinition使用的beanName是org.springframework.context.annotation.internalConfigurationAnnotationProcessor

然后调用registerPostProcessor方法

@Override
     registerBeanDefinition(String beanName,BeanDefinition beanDefinition)
            throws BeanDefinitionStoreException {

        Assert.hasText(beanName,Bean name must not be empty);
        Assert.notNull(beanDefinition,1)">BeanDefinition must not be null);

        if (beanDefinition instanceof AbstractBeanDefinition) {
             {
                ((AbstractBeanDefinition) beanDefinition).validate();
            }
             (BeanDefinitionValidationException ex) {
                 BeanDefinitionStoreException(beanDefinition.getResourceDescription(),beanName,1)">Validation of bean definition Failed,ex);
            }
        }

         从BeanDefinition的一级缓存BeanDefinitionMap中读取BeanDefinition对象,判断是否已经存在
        BeanDefinition existingDefinition = this.beanDefinitionMap.get(beanName);

     // 这里,如果已经存在,说明被重复加载了,那么后面加载的会覆盖前面加载的bean
        if (existingDefinition !=  判断是否允许BeanDefinition重写
            isAllowBeanDefinitionOverriding()) {
                 BeanDefinitionOverrideException(beanName,beanDefinition,existingDefinition);
            }
            else if (existingDefinition.getRole() < beanDefinition.getRole()) {
                 e.g. was ROLE_APPLICATION,now overriding with ROLE_SUPPORT or ROLE_INFRASTRUCTURE
                 (logger.isInfoEnabled()) {
                    logger.info(Overriding user-defined bean definition for bean '" + beanName +
                            ' with a framework-generated bean definition: replacing [
                            existingDefinition + ] with [" + beanDefinition + ]);
                }
            }
            beanDefinition.equals(existingDefinition)) {
                 (logger.isDebugEnabled()) {
                    logger.debug(Overriding bean definition for bean '' with a different definition: replacing [" + existingDefinition +
                            else {
                 (logger.isTraceEnabled()) {
                    logger.trace(' with an equivalent definition: replacing [);
                }
            }
            // 覆盖一级缓存的bean定义
            this.beanDefinitionMap.put(beanName,beanDefinition);
        }
         {
             处理循环引用的问题
             (hasBeanCreationStarted()) {
                 Cannot modify startup-time collection elements anymore (for stable iteration)
                synchronized (.beanDefinitionMap) {
                    .beanDefinitionMap.put(beanName,beanDefinition);
                    List<String> updatedDefinitions = new ArrayList<>(this.beanDefinitionNames.size() + 1);
                    updatedDefinitions.addAll(.beanDefinitionNames);
                    updatedDefinitions.add(beanName);
                    this.beanDefinitionNames = updatedDefinitions;
                    removeManualSingletonName(beanName);
                }
            }
             Still in startup registration phase
                .beanDefinitionNames.add(beanName);
                removeManualSingletonName(beanName);
            }
            this.frozenBeanDefinitionNames = ;
        }

        null || containsSingleton(beanName)) {
            resetBeanDefinition(beanName);
        }
         (isConfigurationFrozen()) {
            clearByTypeCache();
        }
    }

 

这里面的关键代码是标红的部分,将ConfigurationClassPostProcessor放入到了beanDefinitionMap里面

下面的else是处理循环引用的问题,暂时先不要看. 

 3.3 对照整体框架,我们知道ConfigurationClassPostProcessor被解析成beanDefinition放入到BeanDefinitionMap中了

 

 

3.4 初始化ClassPathBeanDefinitionScanner

在this()构造方法里,还初始化了ClassPathBeanDefinitionScanner,这里只说一句. 

this);

 

我们在扫描配置类的时候,确实使用的是ClassPathBeanDefinitionScanner,但是,不是this.scanner对象. 而是自己new的一个ClassPathBeanDefinitionScanner.

这里的scanner仅仅是为了程序员可以手动调用AnnotationConfigApplicationContext对象的scan方法

通过调用context.scan("package name");扫描处理配置类

使用方式如下:

 第一步: 通过AnnotationConfigApplicationContext读取一个配置类
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(MainConfig.);
        context.scan("package");
        Car car = (Car) context.getBean(.println(car.getName());
        context.close();
    }

 

 

到目前为止完成了后置处理器注册为BeanDefinition

 

备注: 

ConfigurationClassPostProcessor是一个工具类,这个类的作用是解析配置类.

工具类有了,那么还得有主角呀,那就是我们上面的配置类. 下面看看配置类的加载

 

四. 读取自定义配置类MainConfig

 注册配置类,入口自然是这里了

();
        // register配置注册类
        register(componentClasses);
                refresh();
    }

 

跟踪进去找到doRegisterBean(...)方法

private <T> void doRegisterBean(Class<T> beanClass,@Nullable String name,@Nullable Class<? extends Annotation>[] qualifiers,@Nullable Supplier<T> supplier,@Nullable BeanDefinitionCustomizer[] customizers) {

         将入参的配置类beanClass构建成AnnotatedGenericBeanDefinition对象
        AnnotatedGenericBeanDefinition abd =  AnnotatedGenericBeanDefinition(beanClass);
        if (.conditionEvaluator.shouldSkip(abd.getMetadata())) {
            ;
        }

        abd.setInstanceSupplier(supplier);
         读取配置类的元数据
        ScopeMetadata scopeMetadata = .scopeMetadataResolver.resolveScopeMetadata(abd);
        abd.setScope(scopeMetadata.getScopeName());
        String beanName = (name != null ? name : this.beanNameGenerator.generateBeanName(abd,.registry));

         处理主类通用定义注解
        AnnotationConfigUtils.processCommonDefinitionAnnotations(abd);
        if (qualifiers != for (Class<? extends Annotation> qualifier : qualifiers) {
                if (Primary.class == qualifier) {
                    abd.setPrimary(true);
                }
                if (Lazy. qualifier) {
                    abd.setLazyInit( {
                    abd.addQualifier( AutowireCandidateQualifier(qualifier));
                }
            }
        }
        if (customizers != for (BeanDefinitionCustomizer customizer : customizers) {
                customizer.customize(abd);
            }
        }
         将MainConfig.java配置类进行解析.放到BeanDefinitionHolder
        BeanDefinitionHolder definitionHolder =  BeanDefinitionHolder(abd,beanName);
        definitionHolder = AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata,definitionHolder,1)">.registry);
        BeanDefinitionReaderUtils.registerBeanDefinition(definitionHolder,this.registry);
    }

 

重点就是红色这句话,其他可以略过,因为我们的配置类很简单,直接看BeanDefinitionReaderUtils.registerBeanDefinition(definitionHolder, this.registry);

我们找到 registry.registerBeanDefinition(beanName,definitionHolder.getBeanDefinition());方法,进入到DefaultListablebeanfactory查看方法,这个方法之前我们已经调用过一次

就是在注册ConfigurationClassPostProcessor的时候,我们需要将其解析为BeanDefinition然后放到BeanDefinitionMap中,这里也是一样的,将我们的配置类MainConfig解析成BeanDefinition放入到BeanDefinitionMap中.

 

这里的代码在整个框架中处于什么位置呢? 将MainConfig解析为BeanDefinition放入到BeanDefinitionMap中

以上两步,一个是将ConfigurationClassPostProcessor配置类后置处理器,也就是解析配置的工具类,解析成BeanDefinition放入到BeanDefinitionMap中

另一个是将我们的目标配置类MainConfig加载到内存,组装成BeanDefinition放入到BeanDefinitionMap中. 

 

到这里,我们完成了两步.

第一步: 准备工具类ConfigurationClassPostProcessor

第二步: 准备配置类MainConfig. 

 

接下俩,就是要使用工具类来解析配置类MainConfig了

 

五. 调用bean工厂的后置处理器invokebeanfactoryPostProcessors(beanfactory);

        register(componentClasses);
        // ioc容器刷新接口--非常重要
        refresh();

在refresh()中有很多步骤,我们重点来看invokebeanfactoryPostProcessors(beanfactory);

 

*
     * refresh是spring最核心的方法,里面包含了整个spring ioc的全过程,包括spring加载bean到销毁bean的全过程
     * 学习spring,就是学习里面的13个方法,如果13个方法都学完了,基本上就打通了
     * @throws BeansException
     * @throws IllegalStateException
     
    @Override
     refresh() throws BeansException,IllegalStateException {
        synchronized (.startupShutdownMonitor) {
             1. 准备刷新上下文环境
            prepareRefresh();

             Tell the subclass to refresh the internal bean factory.
            2. 获取告诉子类初始化bean工厂,不同工厂不同实现
            ConfigurableListablebeanfactory beanfactory = obtainFreshbeanfactory();


             Prepare the bean factory for use in this context.
            3. 对bean工厂进行填充属性
            preparebeanfactory(beanfactory);

             Allows post-processing of the bean factory in context subclasses.
                 4. 留个子类去实现该接口
                postProcessbeanfactory(beanfactory);

                 Invoke factory processors registered as beans in the context.
                
                 *
                 * 调用bean工厂的后置处理器
                 * 我们之前在Reader的时候读取了很多创世纪的PostProcessor后置处理器.
                 * 这里要调用bean工厂的后置处理器. 这么多创世纪的PostProcessor,只有一个PostProcessor实现了
                 * beanfactoryPostProcessor. 那个类就是 ConfigurationClassPostProcessor
                 * 前面已经将ConfigurationClassPostProcessor放入到BeanDefinitionMap中了,* 对应的BeanDefinitionName 是 internalConfigurationAnnotationProcessor
                 *
                 *
                 *
                 */
                invokebeanfactoryPostProcessors(beanfactory);

                 Register bean processors that intercept bean creation.
                 注册bean后置处理器
                registerBeanPostProcessors(beanfactory);

                 Initialize message source for this context.
                 初始化国际化资源处理器
                initMessageSource();

                 Initialize event multicaster for this context.
                 创建事件多播放器
                initApplicationEventMulticaster();

                 Initialize other special beans in specific context subclasses.
                 这个方法通用也是留个子类实现的,spring boot也是从这个方法进行启动
                onRefresh();

                 Check for listener beans and register them.
                 将事件监听器注册到多播放器上
                registerListeners();

                 Instantiate all remaining (non-lazy-init) singletons.
                 实例化剩余的单实例bean
                *
                 * 这个方法就是循环遍历BeanDefinitionMap,调用getBean,去生产bean
                 
                finishbeanfactoryInitialization(beanfactory);

                 Last step: publish corresponding event.
                最后容器刷新 发布刷新时间(spring cloud是从这里启动的 )
                finishRefresh();
            }

            ........
    }

 

invokebeanfactoryPostProcessors(beanfactory);看名字,调用的是Bean工厂的后置处理器,上面分析了,初始化的时候初始化了很多spring原生的后置处理器,这么多后置处理器,其实,只有一个后置处理器实现了beanfactoryPostProcessor,它就是ConfigurationClassPostProcessor,还记得上面的结构图么,拿下来,再看一遍. 

 

 这里调用的时候,原生处理器只会调用ConfigurationClassPostProcessor

protected  invokebeanfactoryPostProcessors(ConfigurableListablebeanfactory beanfactory) {
        /**
         * 获取两处存储beanfactoryPostProcessor的对象,传入供接下来调用
         * 1. 当前bean工厂
         * 2. 和我们自己调用addBeanFacoryPostProcessor自定义beanfactoryPostProcessor
         *
         * 参数: getbeanfactoryPostProcessors() 传了一个工厂的后置处理器的List,这个时候list是空的
         * getbeanfactoryPostProcessors()里面的值是怎么来的呢?
         * 通过在自定义main方法调用context.addbeanfactoryPostProcessor(...);来添加
         *
         * public static void main(String[] args) {
         *         // 第一步: 通过AnnotationConfigApplicationContext读取一个配置类
         *         AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(MainConfig.class);
         *         context.addbeanfactoryPostProcessor(...);
         *         Car car = (Car) context.getBean("car");
         *         System.out.println(car.getName());
         *         context.close();
         * }
         */
        PostProcessorRegistrationDelegate.invokebeanfactoryPostProcessors(beanfactory,getbeanfactoryPostProcessors());

         Detect a LoadTimeWeaver and prepare for weaving,if found in the meantime
         (e.g. through an @Bean method registered by ConfigurationClassPostProcessor)
        if (beanfactory.getTempClassLoader() == null && beanfactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
            beanfactory.addBeanPostProcessor( LoadTimeWeaverAwareProcessor(beanfactory));
            beanfactory.setTempClassLoader( ContextTypeMatchClassLoader(beanfactory.getBeanClassLoader()));
        }
    ......
    }

 

这里要调用bean工厂的后置处理器了. 看上面的注释,注释写的很清晰.

调用PostProcessorRegistrationDelegate.invokebeanfactoryPostProcessors(beanfactory,getbeanfactoryPostProcessors());的时候调用getbeanfactoryPostProcessors()方法

  public List<beanfactoryPostProcessor> getbeanfactoryPostProcessors() {
       return this.beanfactoryPostProcessors;
   }
getbeanfactoryPostProcessors() 返回的是一个工厂的后置处理器的List,这个时候list是空的
getbeanfactoryPostProcessors()里面的值是怎么来的呢?
通过在自定义main方法调用context.addbeanfactoryPostProcessor(...);来添加. 也就是通过main方法手动添加beanfactoryPostProcessor. 如下所示
 main(String[] args) {
            第一步: 通过AnnotationConfigApplicationContext读取一个配置类
           AnnotationConfigApplicationContext context = );
           context.addbeanfactoryPostProcessor(...);
           Car car = (Car) context.getBean();
           System..println(car.getName());
           context.close();
    }

 

接下来重点来了. PostProcessorRegistrationDelegate.invokebeanfactoryPostProcessors(beanfactory,getbeanfactoryPostProcessors()); 方法实现一共分为两大步:

第一步: 调用所有实现了 BeanDefinitionRegistryPostProcessor 接口的bean定义. (BeanDefinitionRegistryPostProcessor带注册功能的后置处理器)

第二步: 调用beanfactoryPostProcessor Bean工厂的后置处理器

第一步: 调用所有实现了 BeanDefinitionRegistryPostProcessor 接口的bean定义. 

来看看源码是如何定义的. 重点看代码的注释,每一部分的功能都有明确标出,注释写的很详细

 

 invokebeanfactoryPostProcessors(
            ConfigurableListablebeanfactory beanfactory,List<beanfactoryPostProcessor> beanfactoryPostProcessors) {

        *
         * 首先,调用BeanDefinitionRegistryPostProcessors的后置处理器
         * 定义已处理的后置处理器
         */
         Invoke BeanDefinitionRegistryPostProcessors first,if any.
        Set<String> processedBeans = new HashSet<>();

        *
         * 这里一共分为两大步:
         * 第一步: 调用所有实现了 BeanDefinitionRegistryPostProcessor 接口的bean定义. (BeanDefinitionRegistryPostProcessor带注册功能的后置处理器)
         * 第二步: 调用beanfactoryPostProcessor Bean工厂的后置处理器
         */

        *********************第一步: 调用所有实现了BeanDefinitionRegistryPostProcessor接口的bean定义  begin*************************** 判断beanfactory是否实现了BeanDefinitionRegistry,实现了该结构就有注册获取Bean定义的能力
         (beanfactory instanceof BeanDefinitionRegistry) {
            BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanfactory;
            List<beanfactoryPostProcessor> regularPostProcessors = new ArrayList<>();
            List<BeanDefinitionRegistryPostProcessor> registryProcessors = ();

             (beanfactoryPostProcessor postProcessor : beanfactoryPostProcessors) {
                 (postProcessor instanceof BeanDefinitionRegistryPostProcessor) {
                    BeanDefinitionRegistryPostProcessor registryProcessor =
                            (BeanDefinitionRegistryPostProcessor) postProcessor;
                    registryProcessor.postProcessBeanDefinitionRegistry(registry);
                    registryProcessors.add(registryProcessor);
                }
                 {
                    regularPostProcessors.add(postProcessor);
                }
            }

             Do not initialize factorybeans here: We need to leave all regular beans
             uninitialized to let the bean factory post-processors apply to them!
             Separate between BeanDefinitionRegistryPostProcessors that implement
             PriorityOrdered,Ordered,and the rest.
            *
             * 这是一个集合,存马上即将要被调用的BeanDefinitionRegistryPostProcessor
             
            List<BeanDefinitionRegistryPostProcessor> currentRegistryProcessors = ();
            // 第一步,调用实现了PriorityOrdered的BeanDefinitionRegistryPostProcessors
             在所有创世纪的后置处理器中,只有 internalConfigurationAnnotationProcessor 实现了 BeanDefinitionRegistryPostProcessors 和 PriorityOrdered
             First,invoke the BeanDefinitionRegistryPostProcessors that implement PriorityOrdered.
            String[] postProcessorNames =
                    beanfactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class,1)">true,1)">false);
             (String ppName : postProcessorNames) {
                 判断beanfactory是否实现了PriorityOrdered接口. 如果实现了,是最优先调用.
                 在整个加载过程中,会调用四次BeanDefinitionRegistryPostProcessor,而实现了PriorityOrdered的接口最先调用
                if (beanfactory.isTypeMatch(ppName,PriorityOrdered.)) {
                     调用beanfactory.getBean实例化创世界的类ppName
                    currentRegistryProcessors.add(beanfactory.getBean(ppName,BeanDefinitionRegistryPostProcessor.));
                    processedBeans.add(ppName);
                }
            }
            sortPostProcessors(currentRegistryProcessors,beanfactory);
            registryProcessors.addAll(currentRegistryProcessors);
            *
             * 第一次调用BeanDefinitionRegistryPostProcessors
             * 在这里典型的BeanDefinitionRegistryPostProcessors就是ConfigurationClassPostProcessor
             * 用于进行bean定义的加载 比如我们的包扫描 @import 等
             
            invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors,registry);
             处理完了,清空currentRegistryProcessors
            currentRegistryProcessors.clear();


            // 第二步: 调用实现 Ordered 的 BeanDefinitionRegistryPostProcessors。
             Next,invoke the BeanDefinitionRegistryPostProcessors that implement Ordered.
            postProcessorNames = beanfactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor. 这时实现了PriorityOrdered.class的postProcessor就不会再被加载进来了,因为processedBeans.contains(ppName) == true
                if (!processedBeans.contains(ppName) && beanfactory.isTypeMatch(ppName,Ordered. 将其放入到currentRegistryProcessors,马上就要被调用
                    currentRegistryProcessors.add(beanfactory.getBean(ppName,1)">));
                    processedBeans.add(ppName);
                }
            }

             对所有的处理器进行排序. 调用了Ordered的方法,会返回排序(一个数字),然后根据数字排序即可
            sortPostProcessors(currentRegistryProcessors,beanfactory);
            registryProcessors.addAll(currentRegistryProcessors);

            *
             * 第二次调用BeanDefinitionRegistryPostProcessors
             * 在这里典型的BeanDefinitionRegistryPostProcessors就是ConfigurationClassPostProcessor
             * 用于进行bean定义的加载 比如我们的包扫描 @import 等
             // 第三步. 调用没有实现任何优先级接口的 BeanDefinitionRegistryPostProcessor
             Finally,invoke all other BeanDefinitionRegistryPostProcessors until no further ones appear.
            boolean reiterate = ;
            while (reiterate) {
                reiterate = ;
                 获取
                postProcessorNames = beanfactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.);
                 (String ppName : postProcessorNames) {
                     已处理过的postProcessor不再处理
                    processedBeans.contains(ppName)) {
                        currentRegistryProcessors.add(beanfactory.getBean(ppName,BeanDefinitionRegistryPostProcessor.));
                        processedBeans.add(ppName);
                        reiterate = ;
                    }
                }
                sortPostProcessors(currentRegistryProcessors,beanfactory);
                registryProcessors.addAll(currentRegistryProcessors);
                *
                 * 第三次调用BeanDefinitionRegistryPostProcessors
                 * 在这里典型的BeanDefinitionRegistryPostProcessors就是ConfigurationClassPostProcessor
                 * 用于进行bean定义的加载 比如我们的包扫描 @import 等
                 
                invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors,registry);
                currentRegistryProcessors.clear();
            }

             Now,invoke the postProcessbeanfactory callback of all processors handled so far.
            
             * 第四步:调用bean工厂的后置处理器
             * registryProcessors: 带有注册功能的bean工厂的后置处理器
             * regularPostProcessors: 不带注册功能的bean工厂的后置处理器
             
            invokebeanfactoryPostProcessors(registryProcessors,beanfactory);
            invokebeanfactoryPostProcessors(regularPostProcessors,beanfactory);
        }

        
             * 如果当前的beanfactory没有实现BeanDefinitionRegistry 说明没有注册Bean定义的能力
             * 那么就直接调用 BeanDefinitionRegistryPostProcessor.postProcessbeanfactory方法
             */

             Invoke factory processors registered with the context instance.
            invokebeanfactoryPostProcessors(beanfactoryPostProcessors,beanfactory);
        }

        *********************第一步: 调用所有实现了BeanDefinitionRegistryPostProcessor接口的bean定义  end************************************************第二步: 调用beanfactoryPostProcessor Bean工厂的后置处理器  begin*************************** Do not initialize factorybeans here: We need to leave all regular beans
         uninitialized to let the bean factory post-processors apply to them!
        String[] postProcessorNames =
                beanfactory.getBeanNamesForType(beanfactoryPostProcessor. Separate between beanfactoryPostProcessors that implement PriorityOrdered, Ordered,and the rest.
         优先排序的后置处理器
        List<beanfactoryPostProcessor> priorityOrderedPostProcessors = ();
        List<String> orderedPostProcessorNames = ();
        List<String> nonOrderedPostProcessorNames =  (String ppName : postProcessorNames) {
             (processedBeans.contains(ppName)) {
                 skip - already processed in first phase above
            }
            )) {
                priorityOrderedPostProcessors.add(beanfactory.getBean(ppName,beanfactoryPostProcessor.));
            }
            )) {
                orderedPostProcessorNames.add(ppName);
            }
             {
                nonOrderedPostProcessorNames.add(ppName);
            }
        }

         首先,调用有优先级排序的后置处理器
        beanfactoryPostProcessors that implement PriorityOrdered.
        sortPostProcessors(priorityOrderedPostProcessors,beanfactory);
        invokebeanfactoryPostProcessors(priorityOrderedPostProcessors,beanfactory);

         第二,调用实现了Ordered排序的后置处理器
        beanfactoryPostProcessors that implement Ordered.
        List<beanfactoryPostProcessor> orderedPostProcessors = (orderedPostProcessorNames.size());
         (String postProcessorName : orderedPostProcessorNames) {
            orderedPostProcessors.add(beanfactory.getBean(postProcessorName,1)">));
        }
        sortPostProcessors(orderedPostProcessors,beanfactory);
        invokebeanfactoryPostProcessors(orderedPostProcessors,1)"> 最后,调用没有实现任何排序接口的beanfactory后置处理器
        beanfactoryPostProcessors.
        List<beanfactoryPostProcessor> nonOrderedPostProcessors = (nonOrderedPostProcessorNames.size());
         (String postProcessorName : nonOrderedPostProcessorNames) {
            nonOrderedPostProcessors.add(beanfactory.getBean(postProcessorName,1)">));
        }
        invokebeanfactoryPostProcessors(nonOrderedPostProcessors,1)">*********************第二步: 调用beanfactoryPostProcessor Bean工厂的后置处理器  end*************************** Clear cached merged bean definitions since the post-processors might have
         modified the original Metadata,e.g. replacing placeholders in values...
        beanfactory.clearMetadataCache();
    }

 

 

 

 

 下面我们就来分析上图所示的内容

 1. 对照源码和上图,我们来看第一次调用

        // 第一次,调用实现了PriorityOrdered的BeanDefinitionRegistryPostProcessors
            String[] postProcessorNames =
                    beanfactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class,true,false);
            PriorityOrdered.class)) {
                    */
            invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors,registry);
            调用.

接下来,执行invokeBeanDefinitionRegistryPostProcessors

这是第一次调用BeanDefinitionRegistryPostProcessors

 

2. 第二次调用BeanDefinitionRegistryPostProcessors

        // 第二步: 调用实现 Ordered 的 BeanDefinitionRegistryPostProcessors。
            调用的时候,依然是获取所有的实现了BeanDefinitionRegistryPostProcessor接口的后置处理器,且这个处理器没有实现过PriorityOrdered也就是没有被上面调用过. 且实现了Ordered接口

这一类添加到currentRegistryProcessors集合中,然后调用invokeBeanDefinitionRegistryPostProcessors处理

这是第二次调用BeanDefinitionRegistryPostProcessor

 

3. 第三次调用BeanDefinitionRegistryPostProcessor

          第三步. 调用没有实现任何优先级接口的 BeanDefinitionRegistryPostProcessor
            调用的是没有实现过任何排序接口的后置处理器. 并将其放入到currentRegistryProcessors,然后执行invokeBeanDefinitionRegistryPostProcessors

 

 

4. 第四次调用

beanfactory callback of all processors handled so far.
/*
 * 调用bean工厂的后置处理器
 * registryProcessors: 带有注册功能的bean工厂的后置处理器
 * regularPostProcessors: 不带注册功能的bean工厂的后置处理器
 */
 调用BeanDefinitionRegistryPostProcessor.postProcessbeanfactory方法----为什么是调用BeanDefinitionRegistryPostProcessor? 因为
 ConfigurationClassPostProcessor 实现了 BeanDefinitionRegistryPostProcessor 和 beanfactoryPostProcessors
invokebeanfactoryPostProcessors(registryProcessors,beanfactory);
 调用beanfactoryPostProcessor 自设的(ConfigurationClassPostProcessor没有)
invokebeanfactoryPostProcessors(regularPostProcessors,beanfactory);

 

ConfigurationClassPostProcessor同时实现了BeanDefinitionRegistryPostProcessor 和 beanfactoryPostProcessors,调用的是invokebeanfactoryPostProcessors

 

一共进行了4次调用

总结: 优先处理的是实现了PriorityOrdered的后置处理器,然后调用实现了Order接口的后置处理器,最后调用了没有实现任何排序方法的后置处理器. 最后调用工厂类方法.

 

下面我们来具体分析invokebeanfactoryPostProcessors(registryProcessors,beanfactory);

 

5. 提问: 检验一下是否理解了上面四个步骤 

 

1. ConfigurationClassPostProcessor会调用1234哪几步?

因为ConfigurationClassPostProcessor实现了BeanDefinitionRegistryPostProcessor和beanfactoryPostProcessor,PriorityOrdered,因此会调用1,1)">4

2. 如果自己定义了一个MybeanfactoryPostProcessor会调用1234那几步?

package com.lxl.www.iocbeanlifecicle;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.ConfigurableListablebeanfactory;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.BeanDefinitionRegistryPostProcessor;
import org.springframework.beans.factory.support.RootBeanDefinition;
import org.springframework.stereotype.Component;

@Component
 MybeanfactoryPostProcessor implements BeanDefinitionRegistryPostProcessor {
   @Override
    postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
      
   }

   @Override
    postProcessbeanfactory(ConfigurableListablebeanfactory beanfactory) throws BeansException {

   }
}


因为MybeanfactoryPostProcessor是自定义的,没有实现任何PriorityOrdered 或者 Order,因此,会调用3,1)">4

 

二. 详细研究第四步, invokebeanfactoryPostProcessors(registryProcessors,beanfactory);的逻辑.

我们在这一步打个断点,然后跟着断点一步一步点击进去

 

 

 这是registryProcessors里面只有一个后置处理器,就是ConfigurationClassPostProcessor. 

然后进入到ConfigurationClassPostProcessor.postProcessbeanfactory(ConfigurableListablebeanfactory beanfactory)方法

 postProcessbeanfactory(ConfigurableListablebeanfactory beanfactory) {
        int factoryId = System.identityHashCode(beanfactory);
        .factoriesPostProcessed.contains(factoryId)) {
             IllegalStateException(
                    postProcessbeanfactory already called on this post-processor against  beanfactory);
        }
        .factoriesPostProcessed.add(factoryId);
        .registriesPostProcessed.contains(factoryId)) {
             BeanDefinitionRegistryPostProcessor hook apparently not supported...
             Simply call processConfigurationClasses lazily at this point then.
            processConfigBeanDefinitions((BeanDefinitionRegistry) beanfactory);
        }

        // 使用 cglib 配置类进行代理,因为@Bean方法到时候要进行创建Bean的实例.
        enhanceConfigurationClasses(beanfactory);
        beanfactory.addBeanPostProcessor( ImportAwareBeanPostProcessor(beanfactory));
    }

 

这里先看enhanceConfigurationClasses(beanfactory);方法 

 enhanceConfigurationClasses(ConfigurableListablebeanfactory beanfactory) {
        Map<String,AbstractBeanDefinition> configBeanDefs = new LinkedHashMap<> (String beanName : beanfactory.getBeanDefinitionNames()) {
            BeanDefinition beanDef = beanfactory.getBeanDefinition(beanName);
            Object configClassAttr = beanDef.getAttribute(ConfigurationClassUtils.CONFIGURATION_CLASS_ATTRIBUTE);
            MethodMetadata methodMetadata =  (beanDef instanceof AnnotatedBeanDefinition) {
                methodMetadata = ((AnnotatedBeanDefinition) beanDef).getFactoryMethodMetadata();
            }
            if ((configClassAttr != null || methodMetadata != null) && beanDef instanceof AbstractBeanDefinition) {
                 Configuration class (full or lite) or a configuration-derived @Bean method
                 -> resolve bean class at this point...
                AbstractBeanDefinition abd = (AbstractBeanDefinition) beanDef;
                abd.hasBeanClass()) {
                     {
                        abd.resolveBeanClass(.beanClassLoader);
                    }
                     (Throwable ex) {
                         IllegalStateException(
                                Cannot load configuration class:  beanDef.getBeanClassName(),ex);
                    }
                }
            }

            /**
             * 只有full版配置才会创建cglib代理
             * full是怎么来的呢? 我们使用@Configuration注解了,在加载的时候,就会设置为full
             * 当设置为full以后,我们在调用的时候,就会创建一个cglib动态代理.
             *
             * 为什么要创建动态代理呢?
             * 动态代理可以保证,每次创建的bean对象只有一个
             *
             * 那么加@Configuration和不加本质上的区别是什么?
             * 当在配置类中一个@Bean使用方法的方式引入另一个Bean的时候,如果不加@Configuration注解,就会重复加载Bean
             * 如果加了@Configuration,则会在这里创建一个cglib代理,当调用了@Bean方法是会先检测容器中是否存在这个Bean,如果不存在则创建,存在则直接使用.
             */
             (ConfigurationClassUtils.CONFIGURATION_CLASS_FULL.equals(configClassAttr)) {
                (beanDef instanceof AbstractBeanDefinition)) {
                    new BeanDefinitionStoreException(Cannot enhance @Configuration bean definition '
                            beanName + ' since it is not stored in an AbstractBeanDefinition subclassif (logger.isInfoEnabled() && beanfactory.containsSingleton(beanName)) {
                    logger.info(' since its singleton instance has been created too early. The typical cause " +
                            is a non-static @Bean method with a BeanDefinitionRegistryPostProcessor return type: Consider declaring such methods as 'static'.);
                }
                configBeanDefs.put(beanName,(AbstractBeanDefinition) beanDef);
            }
        }
         (configBeanDefs.isEmpty()) {
             nothing to enhance -> return immediately
            ;
        }

        ConfigurationClassEnhancer enhancer =  ConfigurationClassEnhancer();
        for (Map.Entry<String,AbstractBeanDefinition> entry : configBeanDefs.entrySet()) {
            AbstractBeanDefinition beanDef = entry.getValue();
             If a @Configuration class gets proxied,always proxy the target class
            beanDef.setAttribute(AutoProxyUtils.PRESERVE_TARGET_CLASS_ATTRIBUTE,Boolean.TRUE);
             Set enhanced subclass of the user-specified bean class
            Class<?> configClass = beanDef.getBeanClass();
            Class<?> enhancedClass = enhancer.enhance(configClass,1)">.beanClassLoader);
            if (configClass != enhancedClass) {
                 (logger.isTraceEnabled()) {
                    logger.trace(String.format(Replacing bean definition '%s' existing class '%s' with enhanced class '%s'属性configurationClass的值是full. 只有full版配置才会创建cglib代理

那么有下面几个问题: 

问题1: full版本配置是什么呢?

我们使用@Configuration注解了,就会将configurationClass属性设置为full.当设置为full以后,就会创建一个cglib动态代理.

问题2: 为什么要创建动态代理呢?

动态代理可以保证,每次创建的bean对象只有一个

问题3:那么加@Configuration和不加本质上的区别是什么?

当在配置类中一个@Bean使用方法的方式引入另一个Bean的时候,就会重复加载Bean.如果加了@Configuration,存在则直接使用.

问题4:full是怎么来的呢?

这是在上面调用invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors,registry);接口的时候,标记的是full还是Lite

下面来看一下源码

 

 在这里一步,执行的时候,进行了这个类是full的还是lite,继续忘下看

 

 此时满足条件的postProcessor只有一个,那就是ConfigurationClassPostProcessor. 下面直接看ConfigurationClassPostProcessor.postProcessBeanDefinitionRegistry()方法

 

 前面都是一些条件判断,重点看processConfigBeanDefinitions(registry);

 

 在这里,这个方法判断了,这个类是full的还是lite的. 下面直接上代码

*
     * Check whether the given bean definition is a candidate for a configuration class
     * (or a nested component class declared within a configuration/component class,* to be auto-registered as well),and mark it accordingly.
     * @param beanDef the bean definition to check
     * @param MetadataReaderFactory the current factory in use by the caller
     * @return whether the candidate qualifies as (any kind of) configuration class
     static boolean checkConfigurationClassCandidate(
            BeanDefinition beanDef,MetadataReaderFactory MetadataReaderFactory) {

        String className = beanDef.getBeanClassName();
        if (className == null || beanDef.getFactoryMethodName() != return ;
        }

        AnnotationMetadata Metadata;
         获取元数据
        if (beanDef instanceof AnnotatedBeanDefinition &&
                className.equals(((AnnotatedBeanDefinition) beanDef).getMetadata().getClassName())) {
             Can reuse the pre-parsed Metadata from the given BeanDefinition...
            Metadata = ((AnnotatedBeanDefinition) beanDef).getMetadata();
        }
        if (beanDef instanceof AbstractBeanDefinition && ((AbstractBeanDefinition) beanDef).hasBeanClass()) {
             Check already loaded Class if present...
             since we possibly can't even load the class file for this Class.
            Class<?> beanClass = ((AbstractBeanDefinition) beanDef).getBeanClass();
            if (beanfactoryPostProcessor.class.isAssignableFrom(beanClass) ||
                    BeanPostProcessor.
                    AopInfrastructureBean.
                    EventListenerFactory..isAssignableFrom(beanClass)) {
                ;
            }
            Metadata = AnnotationMetadata.introspect(beanClass);
        }
         {
                MetadataReader MetadataReader = MetadataReaderFactory.getMetadataReader(className);
                Metadata = MetadataReader.getAnnotationMetadata();
            }
             (IOException ex) {
                Could not find class file for introspecting configuration annotations: 
                            className,ex);
                }
                ;
            }
        }

         判断元数据中是否包含Configuration注解
        Map<String,Object> config = Metadata.getAnnotationAttributes(Configuration..getName());
        /**
         * 判断,proxyBeanMethods属性是否为true,如果为true就是一个完全的类,* 也就是带有@Configuration注解,设置Configuration_class属性为full
         *
         * proxyBeanMethods配置类是用来指定@Bean注解标注的方法是否使用代理,
         * 默认是true使用代理,直接从IOC容器之中取得对象;
         * 如果设置为false,也就是不使用注解,每次调用@Bean标注的方法获取到的对象和IOC容器中的都不一样,是一个新的对象,所以我们可以将此属性设置为false来提高性能。
         */
        if (config != null && !Boolean.FALSE.equals(config.get(proxyBeanMethods))) {
            beanDef.setAttribute(CONFIGURATION_CLASS_ATTRIBUTE,CONFIGURATION_CLASS_FULL);
        }
        // 判断是不是带了@Component,@ComponentScan @Import @ImportResource @Bean注解,// 如果带有这几种注解,就将其Configuration_class属性为lite类型的配置类
         isConfigurationCandidate(Metadata)) {
            beanDef.setAttribute(CONFIGURATION_CLASS_ATTRIBUTE,CONFIGURATION_CLASS_LITE);
        }
         It's a full or lite configuration candidate... Let's determine the order value,if any.
        Integer order = getOrder(Metadata);
        if (order != ) {
            beanDef.setAttribute(ORDER_ATTRIBUTE,order);
        }

        ;
    }

 

上面主要是获取元数据,然后判断元数据中是否有Configuration注解. 如果有,返回其属性. 我们判断其属性中proxyBeanMethods是否true,如果是true,那么将其设置为full. 

如果配置中带有@Component,@ComponentScan @Import @ImportResource @Bean这几种属性之一,那么就将其设置为lite.

 

问题5: cglib动态代理做了什么事情呢?

不看源码的情况下,简单可以理解为,去ioc工厂里面通过getBean("car") 查询了看ioc中是否有这个对象,如果有就取出来,不再另创建. 

这也是@Configuration 和其他注解类似@Component和@ComponentScan的本质区别:

当在配置类中一个@Bean使用方法的方式引入另一个Bean的时候,就会重复创建Bean

如果加了@Configuration,存在则直接使用.

 

下面来看个例子

基础类:
 Car  {
    private String name;
     Tank tank;

     String getName() {
         name;
    }

     setName(String name) {
        this.name = Tank getTank() {
         tank;
    }

     setTank(Tank tank) {
        this.tank = tank;
    }
}

 Tank {
     String name;

     Tank() {
        System.out.println(创建一个tank);
    }

     name;
    }

}

 

这是定义的car和tank的基础类

@Configuration
@ComponentScan(basePackages = { MainConfig {

    @Bean("car")
     Car car() {
        Car car =  Car();
        car.setName(zhangsan);
         这里调用了Tank类,tank是通过@Bean注解注入的. 
        car.setTank(tank());
         car;
    }

    @Bean
     Tank tank() {
         Tank();
    }
}

 

当配置类使用了@Configuration注解的时候,运行main方法

);
        context.scan(package);
        Car car2 = (Car) context.getBean(.println(car.getName());
        context.close();
    }
}

 

 

当去掉@Configuration注解的时候,再次运行,我们看到创建了两次tank

//@Configuration
@ComponentScan(basePackages = { MainConfig {

    @Bean()
            car.setTank(tank());
         car;
    }

    @Bean
    new Tank();
    }
}

 

 

在main方法调用了两次(Car) context.getBean("car");

在new一个对象的时候,如果不取ioc容器中取,那么每一次都会创建一个新的.

在ioc容器中,car对象只有一个,但是在构建car的时候,调用了tank,tank在ioc容器中却不一定只有一份. 只有使用了@Configuration,表示需要使用cglib动态代理查找tank类,保证ioc容器中只有一份.

 

 

7. 详细研究四次调用中的第一次调用.  通过分析跟踪@ComponentScan注解是如何解析的,

通过跟踪@ComponentScan注解是如何解析的, 分来理解BeanDefinitionScan,BeanDefinitionRegistry,BeanDefinitionReader是如何工作的. 

 

 invokebeanfactoryPostProcessors(
            ConfigurableListablebeanfactory beanfactory,调用BeanDefinitionRegistryPostProcessors 的后置处理器
         * 定义已处理的后置处理器
         ();
             调用beanfactory.getBean实例化配置类的后置处理器(创世界的类ppName),也就是初始化,实例化,赋值属性.
                    currentRegistryProcessors.add(beanfactory.getBean(ppName,BeanDefinitionRegistryPostProcessor.class));
                    processedBeans.add(ppName);
                }
            }
            sortPostProcessors(currentRegistryProcessors,清空currentRegistryProcessors
            currentRegistryProcessors.clear();

这里也有两大步

第一步: 初始化bean工厂的后置处理器

  通过调用beanfactory.getBean(ppName,BeanDefinitionRegistryPostProcessor.class) 初始化了bean工厂的后置处理器,

第二步: 解析配置

   调用invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors,registry);调用beanDefinitionRegistry的后置处理器. 筛选出符合条件的配置类. 

 

如上图所示,最后筛选出的配置类只有MainConfig配置类. 也就是说configCandidates配置候选集合中只有一个MainConfig

      // 创建一个ConfigurationClassParser对象,解析@Configuration class
        ConfigurationClassParser parser = new ConfigurationClassParser(
                this.MetadataReaderFactory,this.problemReporter,this.environment,this.resourceLoader,this.componentScanBeanNameGenerator,registry);

        Set<BeanDefinitionHolder> candidates = new LinkedHashSet<>(configCandidates);
        Set<ConfigurationClass> alreadyParsed = (configCandidates.size());
        do {
            // 执行解析
            parser.parse(candidates);
            parser.validate();

 

然后,接下来创建了一个对象ConfigurationClassParser,这是一个配置类解析器. 下面将使用这个解析器解析配置类.

重点是如何解析的,代码已重点标注出来了.

 // 执行解析
parser.parse(candidates);

我们这里是通过注解解析的,所以直接看下面的代码

void parse(Set<BeanDefinitionHolder> configCandidates) {
         循环配置类
         (BeanDefinitionHolder holder : configCandidates) {
            BeanDefinition bd = holder.getBeanDefinition();
             真正的解析bean定义:通过注解元数据解析
                 (bd instanceof AnnotatedBeanDefinition) {
                    parse(((AnnotatedBeanDefinition) bd).getMetadata(),holder.getBeanName());
                }
......
}

 

解析主要做了几件事呢?如下图:

 

 解析配置类,看看配置类是否含有如上标记的注解,如果有,则调用响应的返回对其进行解析,处理.

下面来看看源码. 是如何处理这一块的.

*
     * 在这里会解析@Component  @PropertySources @ComponentScan @ImportResource
     * @param configClass
     * @param sourceClass
     * @param filter
     * @return
     * @throws IOException
     
    @Nullable
    protected final SourceClass doProcessConfigurationClass(
            ConfigurationClass configClass,SourceClass sourceClass,Predicate<String> filter)
            throws IOException {

        // 1. 处理@Component注解,判断元数据是否带有Component注解
        if (configClass.getMetadata().isAnnotated(Component..getName())) {
             Recursively process any member (nested) classes first
            processMemberClasses(configClass,sourceClass,filter);
        }

         Process any @PropertySource annotations
        // 2. 处理@PropertySource 注解,判断元数据是否带有@PropertySource注解
         (AnnotationAttributes propertySource : AnnotationConfigUtils.attributesForRepeatable(
                sourceClass.getMetadata(),PropertySources.)) {
            .environment instanceof ConfigurableEnvironment) {
                processPropertySource(propertySource);
            }
             {
                logger.info(Ignoring @PropertySource annotation on [" + sourceClass.getMetadata().getClassName() +
                        ]. Reason: Environment must implement ConfigurableEnvironment);
            }
        }

         Process any @ComponentScan annotations
         3. 处理@ComponentScan注解,判断元数据是否带有@ComponentScan注解
        *
         * 这里mainConfig配置类中有两个注解,一个是@Configuration,一个是@ComponentScan. 在这里,我们看一下@ComponentScan
         componentScans 拿到的就是ComponentScan注解里的属性
        Set<AnnotationAttributes> componentScans = AnnotationConfigUtils.attributesForRepeatable(
                sourceClass.getMetadata(),ComponentScans.if (!componentScans.isEmpty() &&
                !.conditionEvaluator.shouldSkip(sourceClass.getMetadata(),ConfigurationPhase.REGISTER_BEAN)) {
             (AnnotationAttributes componentScan : componentScans) {
                 The config class is annotated with @ComponentScan -> perform the scan immediately
                 解析扫描出来的类,将其解析为BeanDefinitionHolder对象,并放入到scannedBeanDefinitions中
                 这正的解析ComponentScans和ComponentScan中的配置
                Set<BeanDefinitionHolder> scannedBeanDefinitions =
                        .componentScanParser.parse(componentScan,sourceClass.getMetadata().getClassName());
                 循环处理包扫描出来的bean定义
                 Check the set of scanned definitions for any further config classes and parse recursively if needed
                 (BeanDefinitionHolder holder : scannedBeanDefinitions) {
                    BeanDefinition bdCand = holder.getBeanDefinition().getOriginatingBeanDefinition();
                    if (bdCand == ) {
                        bdCand = holder.getBeanDefinition();
                    }
                     判断当前扫描出来的是不是一个配置类,如果是的话,直接进行递归解析.
                    if (ConfigurationClassUtils.checkConfigurationClassCandidate(bdCand,1)">.MetadataReaderFactory)) {
                        parse(bdCand.getBeanClassName(),holder.getBeanName());
                    }
                }
            }
        }

        // 4. 处理@Import注解
         Process any @Import annotations
        processImports(configClass,getImports(sourceClass),filter,1)">);

        // 5. 处理@ImportResource注解
         Process any @ImportResource annotations
        AnnotationAttributes importResource =
                AnnotationConfigUtils.attributesFor(sourceClass.getMetadata(),ImportResource.if (importResource != ) {
            String[] resources = importResource.getStringArray(locations);
            Class<? extends BeanDefinitionReader> readerClass = importResource.getClass(reader (String resource : resources) {
                String resolvedResource = .environment.resolverequiredPlaceholders(resource);
                configClass.addImportedResource(resolvedResource,readerClass);
            }
        }

        // 6. 处理@Bean注解
         Process individual @Bean methods
        Set<MethodMetadata> beanMethods = retrieveBeanMethodMetadata(sourceClass);
         (MethodMetadata methodMetadata : beanMethods) {
            configClass.addBeanMethod( BeanMethod(methodMetadata,configClass));
        }

         处理默认方法
         Process default methods on interfaces
        processInterfaces(configClass,sourceClass);

         处理超类
         Process superclass,if any
         (sourceClass.getMetadata().hasSuperClass()) {
            String superclass = sourceClass.getMetadata().getSuperClassName();
            if (superclass != null && !superclass.startsWith(java") &&
                    !.knownSuperclasses.containsKey(superclass)) {
                .knownSuperclasses.put(superclass,configClass);
                 Superclass found,return its annotation Metadata and recurse
                 sourceClass.getSuperClass();
            }
        }

         No superclass -> processing is complete
        ;
    }

 

下面我们重点看对@ComponentScan和@ComponentScans注解的解析,为什么看他呢? 因为很多注解都标记了@Component注解. 

比如@Service注解,本身使用@Component

 

 再来看@Controller注解,其实质也是一个@Component注解

 

 我们在自定义配置类的时候,会使用@ComponentScan注解. 并传递一个包,作为扫描包. 如MainConfig配置

 

 这就会扫描包下所有的配置类. 

它主要的逻辑如下:

 

 在拿到@ComponentScan注解以后,会对其进行parse. 主要解析里面的注解. 并对每一个注解进行处理. 处理后将其添加到scanner属性中. 最后调用scanner.doScan(....)方法.

源码如下:

 解析配置
    public Set<BeanDefinitionHolder> parse(AnnotationAttributes componentScan,final String declaringClass) {
        // 定义了一个类路径扫描器ClassPathBeanDefinitionScanner
         这里的scanner用于读取配置类
        ClassPathBeanDefinitionScanner scanner = new ClassPathBeanDefinitionScanner(this.registry,componentScan.getBoolean("useDefaultFilters"),this.resourceLoader);

        // 1. 判断是否有nameGenerator注解
         为扫描器设置beanName的生成器对象,并赋值给scanner,BeanNameGenerator的作用是为bean definitions生成Bean名字的接口
        Class<? extends BeanNameGenerator> generatorClass = componentScan.getClass(nameGenerator);
        boolean useInheritedGenerator = (BeanNameGenerator. generatorClass);
        scanner.setBeanNameGenerator(useInheritedGenerator ? .beanNameGenerator :
                BeanUtils.instantiateClass(generatorClass));

        // 2. 判断是否有scopedProxy注解
        ScopedProxyMode scopedProxyMode = componentScan.getEnum(scopedProxyif (scopedProxyMode != ScopedProxyMode.DEFAULT) {
            scanner.setScopedProxyMode(scopedProxyMode);
        }
         {
            Class<? extends ScopeMetadataResolver> resolverClass = componentScan.getClass(scopeResolver);
            scanner.setScopeMetadataResolver(BeanUtils.instantiateClass(resolverClass));
        }

        scanner.setResourcePattern(componentScan.getString(resourcePattern));

        // 3. 判断属性中是否有includeFilters属性,有的话就添加到scanner中
         设置componentScan中包含的过滤器 -- 在使用注解的时候配置了包含和排除的过滤器,这里进行处理
        for (AnnotationAttributes filter : componentScan.getAnnotationArray(includeFilters (TypeFilter typeFilter : typeFiltersFor(filter)) {
                scanner.addIncludeFilter(typeFilter);
            }
        }

        // 4. 判断属性总是否有excludeFilters属性,有的话放到scnanner中
         设置componentScan中排除的过滤器
        excludeFilters (TypeFilter typeFilter : typeFiltersFor(filter)) {
                scanner.addExcludeFilter(typeFilter);
            }
        }

        // 5. 判断是否有lazyInit属性
         获取配置类中懒加载初始化的属性
        boolean lazyInit = componentScan.getBoolean(lazyInit (lazyInit) {
            scanner.getBeanDefinitionDefaults().setLazyInit();
        }

        Set<String> basePackages = ();

        // 6. 判断是否有basePackages属性
         获取basePackages属性,也就是我们定义的包扫描路径
        String[] basePackagesArray = componentScan.getStringArray(basePackages (String pkg : basePackagesArray) {
            String[] tokenized = StringUtils.tokenizeToStringArray(.environment.resolvePlaceholders(pkg),ConfigurableApplicationContext.CONFIG_LOCATION_DELIMITERS);
            Collections.addAll(basePackages,tokenized);
        }
        for (Class<?> clazz : componentScan.getClassArray(basePackageClasses)) {
            basePackages.add(ClassUtils.getPackageName(clazz));
        }
         (basePackages.isEmpty()) {
            basePackages.add(ClassUtils.getPackageName(declaringClass));
        }

        scanner.addExcludeFilter(new AbstractTypeHierarchyTraversingFilter(false,1)">) {
            @Override
             boolean matchClassName(String className) {
                 declaringClass.equals(className);
            }
        });

        // 调用scanner.doScan()方法,扫描basePackages包
         scanner.doScan(StringUtils.toStringArray(basePackages));
    }

 

调用doScan方法扫描配置类. 我们来看看主要做了哪些事情

 

 

 第一步: 找到所有候选的BeanDefinition.

  上面解析出了@ComponentScan注解传递过来的basePackages包. 扫描包中所有的类,得到候选类. 

  扫描的时候做了几件事呢? 看最上图最右侧部分. 这扫描出来就是我们的目标类.

 第二步: 解析这些准目标类. 

第三步: 设置默认的beanDefinition属性

*
     * 设置默认的bean定义的信息
     * Apply the provided default values to this bean.
     * @param defaults the default settings to apply
     * @since 2.5
      applyDefaults(BeanDefinitionDefaults defaults) {
         设置这个类是不是懒加载的
        Boolean lazyInit = defaults.getLazyInit();
        if (lazyInit != ) {
            setLazyInit(lazyInit);
        }
         设置默认的自动装配方式
        setAutowireMode(defaults.getAutowireMode());
        setDependencyCheck(defaults.getDependencyCheck());
         设置初始化方法名称
        setInitMethodName(defaults.getInitMethodName());
         是否可以调用InitMethod方法
        setEnforceInitMethod();
        setDestroyMethodName(defaults.getDestroyMethodName());
         是否可以调用DestroyMethod方法
        setEnforceDestroyMethod();
    }

 

 第四步: 将解析出来的bean定义注册到ioc容器中

 这里就调用了BeanDefinitionReaderUtils.registerBeanDefinition注册bean定义. 之前注册过配置类,这里和其是一样的. 所以不再赘述了

 

这里有两个细节:

1. excludeFilter中排除了自己

 定义了一个类路径扫描器ClassPathBeanDefinitionScanner
         这里的scanner用于读取配置类
        ClassPathBeanDefinitionScanner scanner = .registry,componentScan.getBoolean(useDefaultFilters"),1)">this.environment,1)">.resourceLoader);

         1. 判断是否有nameGenerator注解
         为扫描器设置beanName的生成器对象
        Class<? extends BeanNameGenerator> generatorClass = componentScan.getClass(.beanNameGenerator :
                BeanUtils.instantiateClass(generatorClass));

         2. 判断是否有scopedProxy注解
        ScopedProxyMode scopedProxyMode = componentScan.getEnum());

         3. 判断属性中是否有includeFilters属性,有的话就添加到scanner中
         (TypeFilter typeFilter : typeFiltersFor(filter)) {
                scanner.addIncludeFilter(typeFilter);
            }
        }

         4. 判断属性总是否有excludeFilters属性,有的话放到scnanner中
         (TypeFilter typeFilter : typeFiltersFor(filter)) {
                scanner.addExcludeFilter(typeFilter);
            }
        }

         5. 判断是否有lazyInit属性
         6. 判断是否有basePackages属性
         (basePackages.isEmpty()) {
            basePackages.add(ClassUtils.getPackageName(declaringClass));
        }

         想ExcludeFilter中添加默认的排除类,
        scanner.addExcludeFilter() {
            @Override
            protected boolean matchClassName(String className) {
                /**
                 * declaringClass就是配置类MainConfig,也就是说. 如果当前类是配置类,那么就会排除掉
                 * 这是一个钩子方法,现在不会调用. 后面才调用
                 * 在哪里调用呢?
                  */
                return declaringClass.equals(className);
            }
        });

         调用scanner.doScan()方法,扫描basePackages包
         scanner.doScan(StringUtils.toStringArray(basePackages));
    }

在解析配置类的时候,除了@ComponentScan注解中定义的ExcludeFilter和IncludeFilter以外,还有默认的排除类. 如上加粗字体的部分. 这里是排除了配置类本身,我们这里的配置类是MainConfig,也就说,会排除掉自己. 

       @Override
             boolean matchClassName(String className) {
                *
                 * declaringClass就是配置类MainConfig,现在不会调用. 后面才调用
                 * 在哪里调用呢? 先记住这个钩子方法matchClassName
                  */
                 declaringClass.equals(className);
            }

matchClassName是一个钩子方法. 在执行到这里的时候,不会真的去执行. 什么时候执行呢? 后面调用doScan的时候执行.

protected Set<BeanDefinitionHolder> doScan(String... basePackages) {
        Assert.notEmpty(basePackages,1)">At least one base package must be specified);
        Set<BeanDefinitionHolder> beanDefinitions =  循环包路径
         (String basePackage : basePackages) {
            // 第一步: 找到所有候选的BeanDefinition
            *
             * 在候选的配置类中,排除掉了自己,同时包含了默认的配置类
             
            Set<BeanDefinition> candidates = findCandidateComponents(basePackage);

在寻找候选配置类的时候,进行了排除了配置类本身.

public Set<BeanDefinition> findCandidateComponents(String basePackage) {
        this.componentsIndex !=  indexSupportsIncludeFilters()) {
            return addCandidateComponentsFromIndex(.componentsIndex,basePackage);
        }
        // 扫描basePackages,获取候选类
            return scanCandidateComponents(basePackage);
        }
    }

进入这个方法

private Set<BeanDefinition> scanCandidateComponents(String basePackage) {
        Set<BeanDefinition> candidates = 第一步:  将com.lxl.www.iocbeanlifecicle转换成了物理路径com/lxl/www/iocbeanlifecicle
            String packageSearchPath = ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX +
                    resolveBasePackage(basePackage) + '/' + .resourcePattern;
            第二步:  .getResources(...)读取到了包下所有的类
            Resource[] resources = getResourcePatternResolver().getResources(packageSearchPath);
            boolean traceEnabled = logger.isTraceEnabled();
            boolean debugEnabled = logger.isDebugEnabled();
             (Resource resource : resources) {
                 (traceEnabled) {
                    logger.trace(Scanning  resource);
                }
                第三步:  判断这个类是否是可读的?
                 (resource.isReadable()) {
                     {
                        MetadataReader MetadataReader = getMetadataReaderFactory().getMetadataReader(resource);
                        第四步:  判断这个类是否是我们要排除的 或者 包含的
                        if (isCandidateComponent(MetadataReader)) {
                             通过scnner扫描出来的beanDefinition是ScannedGenericBeanDefinition类型
                            ScannedGenericBeanDefinition sbd =  ScannedGenericBeanDefinition(MetadataReader);
                             设置sbd的原类路径
                            sbd.setSource(resource);

在第四步的时候调用isCandidateComponent(MetadataReader,这里就判断了是否是包含的类,或者是排除的类

 boolean isCandidateComponent(MetadataReader MetadataReader) throws IOException {
         判断这个类类是否是我们设置的要排除的?
         这里依然使用到了策略设计模式. TypeFilter是一个父类,不同子类的TypeFilter会调用不同的match方法
        for (TypeFilter tf : this.excludeFilters) {
            // 在这里面排除类配置类本身
            if (tf.match(MetadataReader,getMetadataReaderFactory())) {
                return false;
            }
        }
         判断这个类是否是我们要包含的?
        for (TypeFilter tf : this.includeFilters) {
            if (tf.match(MetadataReader,getMetadataReaderFactory())) {
                return isConditionMatch(MetadataReader);
            }
        }
        ;
    }

紫色加错的部分是就是判读是否符合排除的类. 红色加错的部分是判断是否是包含的类. 

先来看紫色的部分,排除的类

 boolean  match(MetadataReader MetadataReader,MetadataReaderFactory MetadataReaderFactory)
            throws IOException {

         This method optimizes avoiding unnecessary creation of ClassReaders
         as well as visiting over those readers.
         (matchSelf(MetadataReader)) {
            ;
        }
        ClassMetadata Metadata = MetadataReader.getClassMetadata();
        // 排除配置类.
        if (matchClassName(Metadata.getClassName())) {
            return true;
        }

看到了么,这里调用了matchClassName. 这就是上面定义的钩子方法

        @Override
             boolean matchClassName(String className) {
                 declaringClass.equals(className);
            }

此时declaringClass表示的是当前的配置类,className表示的是目标类,如果当前目标类 == 配置类,那么就放回true. 返回true,则会排除掉

 

2. includeFilter中包含了默认的配置类

下面来看红色加错的部分

;
    }

我们看到这里有this.includeFilters.包含的过滤器. 这里面是有值的

 

 我们没有在配置类MainConfig上设置includeFilter啊,这里面怎么会有值呢?

这是因为我们有默认包含的过滤器,下面看看默认包含的过滤器是在哪里设置的.

首先从入口类点击AnnotationConfigApplicationContext

 

然后在点击this();

 

再点击ClassPathBeanDefinitionScanner

 

 然后一路点击三个this(...)

 

 最后看到上图 registerDefaultFilter();注册默认的过滤器

 

@SuppressWarnings(unchecked registerDefaultFilters() {
         注册默认的filter---第一个: 在includeFilter中增加了Component
        this.includeFilters.add(new AnnotationTypeFilter(Component.class));
        ClassLoader cl = ClassPathScanningCandidateComponentProvider..getClassLoader();
         {
             注册默认的filter---第二个:在includeFilter中增加了 javax.annotation.ManagedBean
            this.includeFilters.add(new AnnotationTypeFilter(
                    ((Class<? extends Annotation>) ClassUtils.forName("javax.annotation.ManagedBean",cl)),false));
            logger.trace(JSR-250 'javax.annotation.ManagedBean' found and supported for component scanning);
        }
         (ClassNotFoundException ex) {
             JSR-250 1.1 API (as included in Java EE 6) not available - simply skip.
        }
         注册默认的filter---第三个:在includeFilter中增加了 javax.inject.Named
            this.includeFilters.add(new AnnotationTypeFilter(
                    ((Class<? extends Annotation>) ClassUtils.forName("javax.inject.Named",false));
            logger.trace(JSR-330 'javax.inject.Named' annotation found and supported for component scanning JSR-330 API not available - simply skip.
        }
    }

如上图看到,注册了3个默认的过滤器. 分别是Component,ManagedBean,Named. 他们都是注解类型的过滤器AnnotationTypeFilter

其中javax.annotation.ManagedBean和javax.inject.Named是jdk提供给我们的.

 

 

 

到此为止,就将MainConfig配置类解析完并注册到ioc容器中了.

 

猜你在找的Spring相关文章