Spring IOC 源码分析(二)- 注解启动方式

一、注解启动准备

1.1 启动类

启动类.png

1.2 SpringInitConfig

// 仅需要配置一下 默认扫描即可
@ComponentScan
public class SpringInitConfig {

}

二、流程图

Spring IOC 注解方式流程.png

2.1 步骤简要说明

public static void main(String[] args) {
        // 使用AnnotationConfigApplicationContext  作为注解的启动类
        // 将 SpringInitConfig 作为启动配置类 注册IOC容器
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(SpringInitConfig.class);
}
public class AnnotationConfigApplicationContext extends GenericApplicationContext implements AnnotationConfigRegistry {
    
    public AnnotationConfigApplicationContext(Class<?>... annotatedClasses) {
        // 1. 初始化IOC容器
        this();
        // 2. 向IOC容器注册 SpringInitConfig
        register(annotatedClasses);
        // 3. 调用 AbstactApplicationContext 完成 注解的扫描 和 IOC 加载 
        refresh();
    }

}
  1. 初始化IOC容器
    // 父类无参构造函数
    public GenericApplicationContext() {
        this.beanFactory = new DefaultListableBeanFactory();
    }
    // AnnotationConfigApplicationContext 自身无参构造函数
    public AnnotationConfigApplicationContext() {
        // 向Spring IOC 容器中 注册一些 注解方式启动所 必须的类。
        this.reader = new AnnotatedBeanDefinitionReader(this);
        // 实例化一个Bean扫描器 (注册了一些默认的过滤器)
        this.scanner = new ClassPathBeanDefinitionScanner(this);
    }

    // 通常我们认为可能这里可能仅仅只是做一些初始化配置,实例化了两个对象。从而忽略掉一个很关键的类。
    // 这里需要点进去看看实例化对象时,又做了一些很重要的事情。不要小看这个 new() ,不要一看到 new() 就认为没干其他事情,就跳过了。

this()调用的是自身以及父类无参的构造函数。 自身无参构造函数中实例化了两个对象,reader、scander 。

reader 使用的是 AnnotatedBeanDefinitionReader,见名猜意,这个应该是 读取 带注解的Bean对象。
点进去之后,我们发现他向IOC容器中注入了一些类,这些类都是Spring注解方式启动所必须的类。这里先记住一个关键类,ConfigurationClassPostProcessor。

// AnnotationConfigUtils类
public static Set<BeanDefinitionHolder> registerAnnotationConfigProcessors(
            BeanDefinitionRegistry registry, @Nullable Object source) {
        // 开始向IOC 容器注册 BeanPostProcess 的各种实现类

        DefaultListableBeanFactory beanFactory = unwrapDefaultListableBeanFactory(registry);
        if (beanFactory != null) {
            if (!(beanFactory.getDependencyComparator() instanceof AnnotationAwareOrderComparator)) {
                beanFactory.setDependencyComparator(AnnotationAwareOrderComparator.INSTANCE);
            }
            if (!(beanFactory.getAutowireCandidateResolver() instanceof ContextAnnotationAutowireCandidateResolver)) {
                beanFactory.setAutowireCandidateResolver(new ContextAnnotationAutowireCandidateResolver());
            }
        }

        Set<BeanDefinitionHolder> beanDefs = new LinkedHashSet<>(4);
        // 对于 IOC 来说重点在这里
        if (!registry.containsBeanDefinition(CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME)) {
            // 这个类主要用于 调用 ClassPathBeanDefinitionScanner 完成注解 扫描 注册IOC容器  
            RootBeanDefinition def = new RootBeanDefinition(ConfigurationClassPostProcessor.class);
            def.setSource(source);
            beanDefs.add(registerPostProcessor(registry, def, CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME));
        }

        if (!registry.containsBeanDefinition(AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME)) {
            // 这个主要用于处理 依赖注入
            RootBeanDefinition def = new RootBeanDefinition(AutowiredAnnotationBeanPostProcessor.class);
            def.setSource(source);
            beanDefs.add(registerPostProcessor(registry, def, AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME));
        }

        if (!registry.containsBeanDefinition(REQUIRED_ANNOTATION_PROCESSOR_BEAN_NAME)) {
            // 这个主要处理 增加了 Required 注解的 实例
            RootBeanDefinition def = new RootBeanDefinition(RequiredAnnotationBeanPostProcessor.class);
            def.setSource(source);
            beanDefs.add(registerPostProcessor(registry, def, REQUIRED_ANNOTATION_PROCESSOR_BEAN_NAME));
        }

        // Check for JSR-250 support, and if present add the CommonAnnotationBeanPostProcessor.
        if (jsr250Present && !registry.containsBeanDefinition(COMMON_ANNOTATION_PROCESSOR_BEAN_NAME)) {
            // 主要处理Resource注解
            RootBeanDefinition def = new RootBeanDefinition(CommonAnnotationBeanPostProcessor.class);
            def.setSource(source);
            beanDefs.add(registerPostProcessor(registry, def, COMMON_ANNOTATION_PROCESSOR_BEAN_NAME));
        }

        // Check for JPA support, and if present add the PersistenceAnnotationBeanPostProcessor.
        if (jpaPresent && !registry.containsBeanDefinition(PERSISTENCE_ANNOTATION_PROCESSOR_BEAN_NAME)) {
            RootBeanDefinition def = new RootBeanDefinition();
            try {
                def.setBeanClass(ClassUtils.forName(PERSISTENCE_ANNOTATION_PROCESSOR_CLASS_NAME,
                        AnnotationConfigUtils.class.getClassLoader()));
            }
            catch (ClassNotFoundException ex) {
                throw new IllegalStateException(
                        "Cannot load optional framework class: " + PERSISTENCE_ANNOTATION_PROCESSOR_CLASS_NAME, ex);
            }
            def.setSource(source);
            beanDefs.add(registerPostProcessor(registry, def, PERSISTENCE_ANNOTATION_PROCESSOR_BEAN_NAME));
        }

        if (!registry.containsBeanDefinition(EVENT_LISTENER_PROCESSOR_BEAN_NAME)) {
            RootBeanDefinition def = new RootBeanDefinition(EventListenerMethodProcessor.class);
            def.setSource(source);
            beanDefs.add(registerPostProcessor(registry, def, EVENT_LISTENER_PROCESSOR_BEAN_NAME));
        }
        if (!registry.containsBeanDefinition(EVENT_LISTENER_FACTORY_BEAN_NAME)) {
            RootBeanDefinition def = new RootBeanDefinition(DefaultEventListenerFactory.class);
            def.setSource(source);
            beanDefs.add(registerPostProcessor(registry, def, EVENT_LISTENER_FACTORY_BEAN_NAME));
        }

        return beanDefs;
    }

ClassPathBeanDefinitionScanner 暂时先跳过,就是初始化过滤 includeFilters 容器。@Component、@ManagedBean、@Named

  1. 注册启动配置类SpringInitConfig

这里简单来说,就是将启动配置类 SpringInitConfig 放入 IOC容器 。简单看一下代码。

//Bean定义读取器向容器注册注解Bean定义类
    <T> void doRegisterBean(Class<T> annotatedClass, @Nullable Supplier<T> instanceSupplier, @Nullable String name,
            @Nullable Class<? extends Annotation>[] qualifiers, BeanDefinitionCustomizer... definitionCustomizers) {

        //根据指定的注解Bean定义类,创建Spring容器中对注解Bean的封装的数据结构
        AnnotatedGenericBeanDefinition abd = new AnnotatedGenericBeanDefinition(annotatedClass);
        if (this.conditionEvaluator.shouldSkip(abd.getMetadata())) {
            return;
        }

        abd.setInstanceSupplier(instanceSupplier);
        //========第一步===========================

        //解析注解Bean定义的作用域,若@Scope("prototype"),则Bean为原型类型;
        //若@Scope("singleton"),则Bean为单例类型
        ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(abd);
        //为注解Bean定义设置作用域
        abd.setScope(scopeMetadata.getScopeName());
        //为注解Bean定义生成Bean名称
        String beanName = (name != null ? name : this.beanNameGenerator.generateBeanName(abd, this.registry));


        //========第二步===========================
        //处理注解Bean定义中的通用注解
        AnnotationConfigUtils.processCommonDefinitionAnnotations(abd);
        //如果在向容器注册注解Bean定义时,使用了额外的限定符注解,则解析限定符注解。
        //主要是配置的关于autowiring自动依赖注入装配的限定条件,即@Qualifier注解
        //Spring自动依赖注入装配默认是按类型装配,如果使用@Qualifier则按名称
        if (qualifiers != null) {
            for (Class<? extends Annotation> qualifier : qualifiers) {
                //如果配置了@Primary注解,设置该Bean为autowiring自动依赖注入装//配时的首选
                if (Primary.class == qualifier) {
                    abd.setPrimary(true);
                }
                //如果配置了@Lazy注解,则设置该Bean为非延迟初始化,如果没有配置,
                //则该Bean为预实例化
                else if (Lazy.class == qualifier) {
                    abd.setLazyInit(true);
                }
                //如果使用了除@Primary和@Lazy以外的其他注解,则为该Bean添加一
                //个autowiring自动依赖注入装配限定符,该Bean在进autowiring
                //自动依赖注入装配时,根据名称装配限定符指定的Bean
                else {
                    abd.addQualifier(new AutowireCandidateQualifier(qualifier));
                }
            }
        }
        for (BeanDefinitionCustomizer customizer : definitionCustomizers) {
            customizer.customize(abd);
        }

        //创建一个指定Bean名称的Bean定义对象,封装注解Bean定义类数据
        BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(abd, beanName);
        //========第三步===========================
        //根据注解Bean定义类中配置的作用域,创建相应的代理对象
        definitionHolder = AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
        //========第四步===========================
        //向IOC容器注册注解Bean类定义对象
        BeanDefinitionReaderUtils.registerBeanDefinition(definitionHolder, this.registry);
    }
  1. refresh() 完成 扫描和IOC注册

这里直接看 第五步 invokeBeanFactoryPostProcessors()

@Override
    public void refresh() throws BeansException, IllegalStateException {
        synchronized (this.startupShutdownMonitor) {
            // Prepare this context for refreshing.
            //1、调用容器准备刷新的方法,获取容器的当时时间,同时给容器设置同步标识
            prepareRefresh();

            // Tell the subclass to refresh the internal bean factory.
            //2、告诉子类启动refreshBeanFactory()方法,Bean定义资源文件的载入从
            //子类的refreshBeanFactory()方法启动
            // 之前XML方式是在这里 进行 初始化 扫描对应的类到 IOC容器中
            // 对于注解来说 这里没有太大的含义了,感兴趣的可以跟进去看一下。
            // 注意看好类图。 这次应该是 GenericApplicationContext 类型
            ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

            // Prepare the bean factory for use in this context.
            //3、为BeanFactory配置容器特性,例如类加载器、事件处理器等
            prepareBeanFactory(beanFactory);

            try {
                // Allows post-processing of the bean factory in context subclasses.
                //4、为容器的某些子类指定特殊的BeanPost事件处理器
                postProcessBeanFactory(beanFactory);

                // Invoke factory processors registered as beans in the context.
                //5、调用所有注册的BeanFactoryPostProcessor的Bean
                invokeBeanFactoryPostProcessors(beanFactory);

                // Register bean processors that intercept bean creation.
                //6、为BeanFactory注册BeanPost事件处理器.
                //BeanPostProcessor是Bean后置处理器,用于监听容器触发的事件
                registerBeanPostProcessors(beanFactory);

                // Initialize message source for this context.
                //7、初始化信息源,和国际化相关.
                initMessageSource();

                // Initialize event multicaster for this context.
                //8、初始化容器事件传播器.
                initApplicationEventMulticaster();

                // Initialize other special beans in specific context subclasses.
                //9、调用子类的某些特殊Bean初始化方法
                onRefresh();

                // Check for listener beans and register them.
                //10、为事件传播器注册事件监听器.
                registerListeners();

                // Instantiate all remaining (non-lazy-init) singletons.
                //11、初始化所有剩余的单例Bean
                finishBeanFactoryInitialization(beanFactory);

                // Last step: publish corresponding event.
                //12、初始化容器的生命周期事件处理器,并发布容器的生命周期事件
                finishRefresh();
            }

            catch (BeansException ex) {
                if (logger.isWarnEnabled()) {
                    logger.warn("Exception encountered during context initialization - " +
                            "cancelling refresh attempt: " + ex);
                }

                // Destroy already created singletons to avoid dangling resources.
                //13、销毁已创建的Bean
                destroyBeans();

                // Reset 'active' flag.
                //14、取消refresh操作,重置容器的同步标识。
                cancelRefresh(ex);

                // Propagate exception to caller.
                throw ex;
            }

            finally {
                // Reset common introspection caches in Spring's core, since we
                // might not ever need metadata for singleton beans anymore...
                //15、重设公共缓存
                resetCommonCaches();
            }
        }
    }

这个方法非常的长这里 我们只需要关注 IOC有关的即可。 (Spring 源码 也有很多大类 大方法、各种 if else 嵌套... )

public static void invokeBeanFactoryPostProcessors(
            ConfigurableListableBeanFactory beanFactory, List<BeanFactoryPostProcessor> beanFactoryPostProcessors) {

        // Invoke BeanDefinitionRegistryPostProcessors first, if any.
        Set<String> processedBeans = new HashSet<>();

        // beanFactoryPostProcessors 一般为空, 需要外部扩展 添加到 beanFactoryPostProcessors 容器中才会有值
        if (beanFactory instanceof BeanDefinitionRegistry) {
            BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory;
            List<BeanFactoryPostProcessor> regularPostProcessors = new LinkedList<>();
            List<BeanDefinitionRegistryPostProcessor> registryProcessors = new LinkedList<>();

            for (BeanFactoryPostProcessor postProcessor : beanFactoryPostProcessors) {
                if (postProcessor instanceof BeanDefinitionRegistryPostProcessor) {
                    BeanDefinitionRegistryPostProcessor registryProcessor =
                            (BeanDefinitionRegistryPostProcessor) postProcessor;
                    registryProcessor.postProcessBeanDefinitionRegistry(registry);
                    registryProcessors.add(registryProcessor);
                }
                else {
                    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.
            List<BeanDefinitionRegistryPostProcessor> currentRegistryProcessors = new ArrayList<>();

            // First, invoke the BeanDefinitionRegistryPostProcessors that implement PriorityOrdered.
            // 第一步,先从IOC容器中获取 已注册的 第一优先级的 BeanDefinitionRegistryPostProcessor 实现类,也就是 ConfigurationClassPostProcessor
            // 这个类就是在 第一步 this() 中添加到 IOC 容器的
            String[] postProcessorNames =
                    beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
            for (String ppName : postProcessorNames) {
                //
                if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
                    // 调用getBean() 实例化 ConfigurationClassPostProcessor 类
                    currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
                    processedBeans.add(ppName);
                }
            }
            sortPostProcessors(currentRegistryProcessors, beanFactory);
            registryProcessors.addAll(currentRegistryProcessors);
            // 实例化完成的类 调用其 postProcessBeanDefinitionRegistry 方法
            // 对于 ConfigurationClassPostProcessor 来说这里主要 会完成 类扫描 和 IOC 初始化,
            // 所以这次重点看这里!!!!  
            invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
            // 清空集合
            currentRegistryProcessors.clear();

            // Next, invoke the BeanDefinitionRegistryPostProcessors that implement Ordered.
            // 第二步,找到第二优先级 的实现类 进行实例化 并调用 postProcessBeanDefinitionRegistry 方法
            postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
            for (String ppName : postProcessorNames) {
                if (!processedBeans.contains(ppName) && beanFactory.isTypeMatch(ppName, Ordered.class)) {
                    currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
                    processedBeans.add(ppName);
                }
            }
            sortPostProcessors(currentRegistryProcessors, beanFactory);
            registryProcessors.addAll(currentRegistryProcessors);
            invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
            currentRegistryProcessors.clear();

            // Finally, invoke all other BeanDefinitionRegistryPostProcessors until no further ones appear.
            // 第三部, 调用 BeanDefinitionRegistryPostProcessors 父类的 方法 也就是 postProcessBeanDefinitionRegistry
            // 前边,第一、第二步拿了,两次实现类了。两次都有 isTypeMatch() 过滤。暂时没有研究 是过滤什么的。但是这里针对的就是剩下那部分
            // 但是这个 while 表示没能看懂。 第三步已经把剩下的都给拿完,处理完了。为什么还要再来一下?意义是什么呢?
            // 如果是考虑 其他地方有动态设置多次情况,那么稳妥起见不应该等设置完让其自行实现处理。多次设置间隔不固定。没有必要用while
            // 那么可能情况为:调用 postProcessBeanDefinitionRegistry 时 又向IOC容器注册了 其他的 BeanDefinitionRegistryPostProcessor
            // 只有在这种套娃情况下 会使用while 纯属猜测,没有实例验证。
            boolean reiterate = true;
            while (reiterate) {
                reiterate = false;
                postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
                for (String ppName : postProcessorNames) {
                    if (!processedBeans.contains(ppName)) {
                        currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
                        processedBeans.add(ppName);
                        reiterate = true;
                    }
                }
                sortPostProcessors(currentRegistryProcessors, beanFactory);
                registryProcessors.addAll(currentRegistryProcessors);
                invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
                currentRegistryProcessors.clear();
            }

            // Now, invoke the postProcessBeanFactory callback of all processors handled so far.
            invokeBeanFactoryPostProcessors(registryProcessors, beanFactory);
            invokeBeanFactoryPostProcessors(regularPostProcessors, beanFactory);
        }

        else {
            // Invoke factory processors registered with the context instance.
            invokeBeanFactoryPostProcessors(beanFactoryPostProcessors, beanFactory);
        }

        // Do not initialize FactoryBeans here: We need to leave all regular beans
        // uninitialized to let the bean factory post-processors apply to them!
        // 这里直接拿 父类的实现,针对那些直接实现 BeanFactoryPostProcessor 的类
        String[] postProcessorNames =
                beanFactory.getBeanNamesForType(BeanFactoryPostProcessor.class, true, false);

        // Separate between BeanFactoryPostProcessors that implement PriorityOrdered,
        // Ordered, and the rest.
        List<BeanFactoryPostProcessor> priorityOrderedPostProcessors = new ArrayList<>();
        List<String> orderedPostProcessorNames = new ArrayList<>();
        List<String> nonOrderedPostProcessorNames = new ArrayList<>();
        // 跟上边的步骤类似  都是  isTypeMatch() 两次, 然后其他的一次。 但是明显这样更清晰。
        // 我猜这里 应该不是一个人写的。 狗头 ~
        for (String ppName : postProcessorNames) {
            if (processedBeans.contains(ppName)) {
                // skip - already processed in first phase above
            }
            else if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
                priorityOrderedPostProcessors.add(beanFactory.getBean(ppName, BeanFactoryPostProcessor.class));
            }
            else if (beanFactory.isTypeMatch(ppName, Ordered.class)) {
                orderedPostProcessorNames.add(ppName);
            }
            else {
                nonOrderedPostProcessorNames.add(ppName);
            }
        }

        // First, invoke the BeanFactoryPostProcessors that implement PriorityOrdered.
        sortPostProcessors(priorityOrderedPostProcessors, beanFactory);
        invokeBeanFactoryPostProcessors(priorityOrderedPostProcessors, beanFactory);

        // Next, invoke the BeanFactoryPostProcessors that implement Ordered.
        List<BeanFactoryPostProcessor> orderedPostProcessors = new ArrayList<>();
        for (String postProcessorName : orderedPostProcessorNames) {
            orderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));
        }
        sortPostProcessors(orderedPostProcessors, beanFactory);
        invokeBeanFactoryPostProcessors(orderedPostProcessors, beanFactory);

        // Finally, invoke all other BeanFactoryPostProcessors.
        // 这里没有使用while 看来不支持 套娃!!
        List<BeanFactoryPostProcessor> nonOrderedPostProcessors = new ArrayList<>();
        for (String postProcessorName : nonOrderedPostProcessorNames) {
            nonOrderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));
        }
        invokeBeanFactoryPostProcessors(nonOrderedPostProcessors, beanFactory);

        // Clear cached merged bean definitions since the post-processors might have
        // modified the original metadata, e.g. replacing placeholders in values...
        beanFactory.clearMetadataCache();
    }

下边我们重点看一下 ConfigurationClassPostProcessor 类,这个类会调用 ClassPathBeanDefinitionScanner 类来完成基于注解方式的扫描,完成IOC容器的初始化。

public class ConfigurationClassPostProcessor implements BeanDefinitionRegistryPostProcessor,
        PriorityOrdered, ResourceLoaderAware, BeanClassLoaderAware, EnvironmentAware {
    // 首先这个类 实现了 BeanDefinitionRegistryPostProcessor  
    // 而 BeanDefinitionRegistryPostProcessor  类又继承了 BeanFactoryPostProcessor 
    // 那么这里有两个 方法需要重点关注一下  postProcessBeanFactory、postProcessBeanDefinitionRegistry
    // 这两个方法都会在 Spring 初始化过程中被调用 refresh() 方法中的 invokeBeanFactoryPostProcessors()

    // 这个方法的调用时机 实际上 会早于 BeanFactoryPostProcessor 
    @Override
    public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) {
        // 为了避免扫描 初始化两次 先生成一个 registryHashCode 用来判断是否已经注册过
        int registryId = System.identityHashCode(registry);
        if (this.registriesPostProcessed.contains(registryId)) {
            throw new IllegalStateException(
                    "postProcessBeanDefinitionRegistry already called on this post-processor against " + registry);
        }
        if (this.factoriesPostProcessed.contains(registryId)) {
            throw new IllegalStateException(
                    "postProcessBeanFactory already called on this post-processor against " + registry);
        }
        this.registriesPostProcessed.add(registryId);
        // 重要的是这里
        processConfigBeanDefinitions(registry);
    }

    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {
        int factoryId = System.identityHashCode(beanFactory);
        if (this.factoriesPostProcessed.contains(factoryId)) {
            throw new IllegalStateException(
                    "postProcessBeanFactory already called on this post-processor against " + beanFactory);
        }
        this.factoriesPostProcessed.add(factoryId);
        // 为了避免扫描 初始化两次 判断 registryHashCode 是否已经注册过
        if (!this.registriesPostProcessed.contains(factoryId)) {
            // BeanDefinitionRegistryPostProcessor hook apparently not supported...
            // Simply call processConfigurationClasses lazily at this point then.
            processConfigBeanDefinitions((BeanDefinitionRegistry) beanFactory);
        }

        enhanceConfigurationClasses(beanFactory);
        beanFactory.addBeanPostProcessor(new ImportAwareBeanPostProcessor(beanFactory));
    }

    /**
     * Build and validate a configuration model based on the registry of
     * {@link Configuration} classes.
     */
    public void processConfigBeanDefinitions(BeanDefinitionRegistry registry) {
        List<BeanDefinitionHolder> configCandidates = new ArrayList<>();
        String[] candidateNames = registry.getBeanDefinitionNames();
        // 获取容器中 已注册的 beanDefinitionNames 找到一些关键的配置启动类。如 @Configuration、@ComponentScan、@Import
        // 我们自定义的启动类 SpringInitConfig 这时已经完成了注册,肯定在其中,这里就是将 该类过滤出来 方便后续解析
        for (String beanName : candidateNames) {
            BeanDefinition beanDef = registry.getBeanDefinition(beanName);
            if (ConfigurationClassUtils.isFullConfigurationClass(beanDef) ||
                    ConfigurationClassUtils.isLiteConfigurationClass(beanDef)) {
                if (logger.isDebugEnabled()) {
                    logger.debug("Bean definition has already been processed as a configuration class: " + beanDef);
                }
            }
            // 重点是这里 我们自定义的启动类 包含了 @ComponentScan 所以会添加到 configCandidates 集合中
            // 这里也顺便扩展一下 SpringBoot 启动类其实也是这种方式 感兴趣的可以点进去看一下。
            // 满足条件包含 类注解:@Configuration、@Component、@ComponentScan、@Import、@ImportResource
            // 方法注解  @Bean
            else if (ConfigurationClassUtils.checkConfigurationClassCandidate(beanDef, this.metadataReaderFactory)) {
                configCandidates.add(new BeanDefinitionHolder(beanDef, beanName));
            }
        }

        // Return immediately if no @Configuration classes were found
        if (configCandidates.isEmpty()) {
            return;
        }
        // 多个类情况适用@Order注解排序
        // Sort by previously determined @Order value, if applicable
        configCandidates.sort((bd1, bd2) -> {
            int i1 = ConfigurationClassUtils.getOrder(bd1.getBeanDefinition());
            int i2 = ConfigurationClassUtils.getOrder(bd2.getBeanDefinition());
            return (i1 < i2) ? -1 : (i1 > i2) ? 1 : 0;
        });

        // Detect any custom bean name generation strategy supplied through the enclosing application context
        SingletonBeanRegistry sbr = null;
        if (registry instanceof SingletonBeanRegistry) {
            sbr = (SingletonBeanRegistry) registry;
            if (!this.localBeanNameGeneratorSet) {
                BeanNameGenerator generator = (BeanNameGenerator) sbr.getSingleton(CONFIGURATION_BEAN_NAME_GENERATOR);
                if (generator != null) {
                    this.componentScanBeanNameGenerator = generator;
                    this.importBeanNameGenerator = generator;
                }
            }
        }

        if (this.environment == null) {
            this.environment = new StandardEnvironment();
        }

        // Parse each @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 = new HashSet<>(configCandidates.size());
        do {
            // 这里开始解析 配置类
            parser.parse(candidates);
            parser.validate();

            Set<ConfigurationClass> configClasses = new LinkedHashSet<>(parser.getConfigurationClasses());
            configClasses.removeAll(alreadyParsed);

            // Read the model and create bean definitions based on its content
            if (this.reader == null) {
                this.reader = new ConfigurationClassBeanDefinitionReader(
                        registry, this.sourceExtractor, this.resourceLoader, this.environment,
                        this.importBeanNameGenerator, parser.getImportRegistry());
            }
            this.reader.loadBeanDefinitions(configClasses);
            alreadyParsed.addAll(configClasses);

            candidates.clear();
            if (registry.getBeanDefinitionCount() > candidateNames.length) {
                String[] newCandidateNames = registry.getBeanDefinitionNames();
                Set<String> oldCandidateNames = new HashSet<>(Arrays.asList(candidateNames));
                Set<String> alreadyParsedClasses = new HashSet<>();
                for (ConfigurationClass configurationClass : alreadyParsed) {
                    alreadyParsedClasses.add(configurationClass.getMetadata().getClassName());
                }
                for (String candidateName : newCandidateNames) {
                    if (!oldCandidateNames.contains(candidateName)) {
                        BeanDefinition bd = registry.getBeanDefinition(candidateName);
                        if (ConfigurationClassUtils.checkConfigurationClassCandidate(bd, this.metadataReaderFactory) &&
                                !alreadyParsedClasses.contains(bd.getBeanClassName())) {
                            candidates.add(new BeanDefinitionHolder(bd, candidateName));
                        }
                    }
                }
                candidateNames = newCandidateNames;
            }
        }
        while (!candidates.isEmpty());

        // Register the ImportRegistry as a bean in order to support ImportAware @Configuration classes
        if (sbr != null) {
            if (!sbr.containsSingleton(IMPORT_REGISTRY_BEAN_NAME)) {
                sbr.registerSingleton(IMPORT_REGISTRY_BEAN_NAME, parser.getImportRegistry());
            }
        }

        if (this.metadataReaderFactory instanceof CachingMetadataReaderFactory) {
            // Clear cache in externally provided MetadataReaderFactory; this is a no-op
            // for a shared cache since it'll be cleared by the ApplicationContext.
            ((CachingMetadataReaderFactory) this.metadataReaderFactory).clearCache();
        }
    }

往下的调用链就不写的那么细了,直接点着走就OK了。这里如果迷路了,直接在ClassPathBeanDefinitionScanner#doScan() 方法处打断点然后直接看Debug调用链信息吧。

image.png
    //类路径Bean定义扫描器扫描给定包及其子包
    protected Set<BeanDefinitionHolder> doScan(String... basePackages) {
        Assert.notEmpty(basePackages, "At least one base package must be specified");
        //创建一个集合,存放扫描到Bean定义的封装类
        Set<BeanDefinitionHolder> beanDefinitions = new LinkedHashSet<>();
        //遍历扫描所有给定的包
        for (String basePackage : basePackages) {
            //调用父类ClassPathScanningCandidateComponentProvider的方法
            //扫描给定类路径,获取符合条件的Bean定义
            //可以找一下这里的 BeanDefinition 到底是哪个,看一下类关系图 这样 下边的几个 if 判断就知道会不会进入了。
            Set<BeanDefinition> candidates = findCandidateComponents(basePackage);
            //遍历扫描到的Bean
            for (BeanDefinition candidate : candidates) {
                //获取Bean定义类中@Scope注解的值,即获取Bean的作用域
                ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(candidate);
                //为Bean设置注解配置的作用域
                candidate.setScope(scopeMetadata.getScopeName());
                //为Bean生成名称
                String beanName = this.beanNameGenerator.generateBeanName(candidate, this.registry);
                //如果扫描到的Bean不是Spring的注解Bean,则为Bean设置默认值,
                //设置Bean的自动依赖注入装配属性等
                if (candidate instanceof AbstractBeanDefinition) {
                    postProcessBeanDefinition((AbstractBeanDefinition) candidate, beanName);
                }
                //如果扫描到的Bean是Spring的注解Bean,则处理其通用的Spring注解
                if (candidate instanceof AnnotatedBeanDefinition) {
                    //处理注解Bean中通用的注解,在分析注解Bean定义类读取器时已经分析过
                    AnnotationConfigUtils.processCommonDefinitionAnnotations((AnnotatedBeanDefinition) candidate);
                }
                //根据Bean名称检查指定的Bean是否需要在容器中注册,或者在容器中冲突
                if (checkCandidate(beanName, candidate)) {
                    BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(candidate, beanName);
                    //根据注解中配置的作用域,为Bean应用相应的代理模式
                    definitionHolder =
                            AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
                    beanDefinitions.add(definitionHolder);
                    //向容器注册扫描到的Bean
                    registerBeanDefinition(definitionHolder, this.registry);
                }
            }
        }
        return beanDefinitions;
    }

总结

经过上边的分析,相信已经大概了解基于注解的IOC加载方式了。下边再回顾一下步骤。

  1. 从 AnnotationConfigApplicationContext 开始,传入启动配置类。完成 reader、scanner实例化,reader实例化过程中向IOC容器注入几个关键的类。比如:ConfigurationClassPostProcessor。

  2. 完成启动配置类自身的 IOC 注入。

  3. 在refresh() 方法中调用 invokeBeanFactoryPostProcessors方法。
    该方法会获取IOC容器中注册的 BeanFactoryPostProcessor 的实现类。
    也就是 第一步注册过的ConfigurationClassPostProcessor。
    因此这里会先完成ConfigurationClassPostProcessor 类的实例化(getBean方法,依赖注入的入口,关注一下),并调用该类的 postProcessBeanDefinitionRegistry() 方法。
    方法会获取所有IOC容器中注册的,符合条件的 配置类。并创建解析类(ConfigurationClassParser),完成对 配置类的解析。
    在解析过程中会解析@ComponentScan标签,完成bean的扫描和 IOC注入工作。(这里也包含@Import、@ImpotSource、@Bean等注解的解析)

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 211,884评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,347评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,435评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,509评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,611评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,837评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,987评论 3 408
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,730评论 0 267
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,194评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,525评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,664评论 1 340
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,334评论 4 330
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,944评论 3 313
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,764评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,997评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,389评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,554评论 2 349

推荐阅读更多精彩内容