Spring源码分析(四)bean工厂初始化阶段

原创 吴就业 100 0 2018-10-31

本文为博主原创文章,未经博主允许不得转载。

本文链接:https://wujiuye.com/article/7b25ae9235ea4b80a1a431895ea9b4b4

作者:吴就业
链接:https://wujiuye.com/article/7b25ae9235ea4b80a1a431895ea9b4b4
来源:吴就业的网络日记
本文为博主原创文章,未经博主允许不得转载。

继续介绍AnnotationConfigApplicationContext工作流程,本篇介绍refresh方法,即bean工厂的初始化阶段。读完本篇你会了解到bean是什么时候被全部扫描成BeanDefinition注入到工厂中的。还有一些后置处理器的职责。

打印bean工厂中的bean

编写一个配置类:SpringConfig.java,使用@Configuration注解。在main方法中使用AnnotationConfigApplicationContext启动spring。目前我们并没有注入任何bean,打印一下当前bean工厂中的bean。

AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(SpringConfig.class);
String[] names = applicationContext.getBeanDefinitionNames();
for(String beanName:names){
     System.out.println(beanName);
}

运行打印结果如下:

org.springframework.context.annotation.internalConfigurationAnnotationProcessor
org.springframework.context.annotation.internalAutowiredAnnotationProcessor
org.springframework.context.annotation.internalRequiredAnnotationProcessor
org.springframework.context.annotation.internalCommonAnnotationProcessor
org.springframework.context.event.internalEventListenerProcessor
org.springframework.context.event.internalEventListenerFactory
springConfig

可以看到,当前bean工厂中竟然有7个bean,除了配置类SpringConfig是我们注入的以外,其它都是spring自动注入的,而且bean的名称都是包含包名的,这是spring为了避免我们会注入同名的bean所以才使用包名+类名的。那么这些bean是什么时候被注入的呢?以及这些bean的作用是什么呢?带着这两个问题来继续分析refresh方法。

这一堆Processor是什么时候注入的

最好在打印出这些bean的名称的时候也把bean的类型打印出来,我这里直接给出打印的结果。

org.springframework.context.annotation.internalConfigurationAnnotationProcessor
org.springframework.context.annotation.ConfigurationClassPostProcessor
org.springframework.context.annotation.internalAutowiredAnnotationProcessor
org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor
org.springframework.context.annotation.internalRequiredAnnotationProcessor
org.springframework.beans.factory.annotation.RequiredAnnotationBeanPostProcessor
org.springframework.context.annotation.internalCommonAnnotationProcessor
org.springframework.context.annotation.CommonAnnotationBeanPostProcessor
org.springframework.context.event.internalEventListenerProcessor
org.springframework.context.event.EventListenerMethodProcessor
org.springframework.context.event.internalEventListenerFactory
org.springframework.context.event.DefaultEventListenerFactory
springConfig
wjy.stu.config.SpringConfig$$EnhancerBySpringCGLIB$$3a397ac0

按实现接口分类:

BeanFactoryPostProcessor:

ConfigurationClassPostProcessor

BeanPostProcessor:

AutowiredAnnotationBeanPostProcessor
RequiredAnnotationBeanPostProcessor
CommonAnnotationBeanPostProcessor

Aware:

EventListenerMethodProcessor

解决问题一:这一堆Processor是什么时候注入的?

可以通过调试手段一步步找出来,最后我在AnnotationConfigApplicationContext的构造方法中,register方法执行之前下断点调试,最终发现这些bean在register方法之前就已经在bean工厂中了。

图片

所以这些bean肯定是在构造方法中注入的,但是在AnnotationConfigApplicationContext方法中以及在其父类构造方法中都没有找到注入这些bean的代码。但是在构造方法中却找到了实例化AnnotatedBeanDefinitionReader和ClassPathBeanDefinitionScanner。register方法最终是调用AnnotatedBeanDefinitionReader实例的register方法完成注册的,所以我猜想这些默认的bean一定是在AnnotatedBeanDefinitionReader的构造方法中注入的。

this.reader = new AnnotatedBeanDefinitionReader(this);
this.scanner = new ClassPathBeanDefinitionScanner(this);

来看下AnnotatedBeanDefinitionReader的构造方法。

public AnnotatedBeanDefinitionReader(BeanDefinitionRegistry registry) {
        this(registry, getOrCreateEnvironment(registry));
}
public AnnotatedBeanDefinitionReader(BeanDefinitionRegistry registry, Environment environment) {
        this.registry = registry;
        this.conditionEvaluator = new ConditionEvaluator(registry, environment, null);
        AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry);
    }

果不其然,在AnnotatedBeanDefinitionReader的构造方法中调用了AnnotationConfigUtils工具类的registerAnnotationConfigProcessors方法注册了注解配置处理器。来看下这个方法的部分源代码。

public static void registerAnnotationConfigProcessors(BeanDefinitionRegistry registry) {
        registerAnnotationConfigProcessors(registry, null);
}

public static Set<BeanDefinitionHolder> registerAnnotationConfigProcessors(
            BeanDefinitionRegistry registry, Object source) {
        ......
        Set<BeanDefinitionHolder> beanDefs = new LinkedHashSet<BeanDefinitionHolder>(4);
        if (!registry.containsBeanDefinition(CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME)) {
            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)) {
            RootBeanDefinition def = new RootBeanDefinition(RequiredAnnotationBeanPostProcessor.class);
            def.setSource(source);
            beanDefs.add(registerPostProcessor(registry, def, REQUIRED_ANNOTATION_PROCESSOR_BEAN_NAME));
        }
        // 检查JSR-250支持,如果存在,添加CommonAnnotationBeanPostProcessor。
        if (jsr250Present && !registry.containsBeanDefinition(COMMON_ANNOTATION_PROCESSOR_BEAN_NAME)) {
            RootBeanDefinition def = new RootBeanDefinition(CommonAnnotationBeanPostProcessor.class);
            def.setSource(source);
            beanDefs.add(registerPostProcessor(registry, def, COMMON_ANNOTATION_PROCESSOR_BEAN_NAME));
        }

        // 检查JPA支持,如果存在,添加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;
    }

这一堆Processor的作用是什么?

spring为什么要注入这一堆Processor,肯定是有作用的,接下来就是通过读源码自己发现这些处理器bean的作用。前面分析过AnnotationConfigApplicationContext构造方法中register方法的执行流程,并没有发现调用这些处理器的地方,所以我们接着分析AnnotationConfigApplicationContext构造方法中register方法执行完成之后执行的refresh方法。

下面给出refresh方法的完整代码以及注释。

@Override
    public void refresh() throws BeansException, IllegalStateException {
        synchronized (this.startupShutdownMonitor) {
            prepareRefresh();
            // 这里获取到的是DefaultListableBeanFactory,前面说过,GenericApplicationContext的子类都是通过持有一个内部bean工厂管理bean的,这个bean工厂就是DefaultListableBeanFactory。
            ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
            // 准备好bean工厂,就是配置bean工厂。
            prepareBeanFactory(beanFactory);
            try {
                // 允许在上下文子类中对bean工厂进行后置处理。
                postProcessBeanFactory(beanFactory);
                // 调用bean工厂的后置处理器。
                invokeBeanFactoryPostProcessors(beanFactory);
                // 注册拦截bean创建的bean后置处理器。
                registerBeanPostProcessors(beanFactory);
                // 初始化消息源。
                initMessageSource();
                // 初始化事件的支持
                initApplicationEventMulticaster();
                // 初始化其他特殊bean。
                onRefresh();
                // 注册监听器bean。
                registerListeners();
                // 实例化所有剩余的(非延迟-init)单例。
                finishBeanFactoryInitialization(beanFactory);
                // 完成刷新发布相应事件
                finishRefresh();
            }
            catch (BeansException ex) {
                // 销毁已经创建的单例。
                destroyBeans();
                // 重置‘active’标志
                cancelRefresh(ex);
                throw ex;
            }
            finally {
                // 重置Spring核心中的普通内容缓存,因为我们可能再也不需要单例bean的元数据了。
                resetCommonCaches();
            }
        }
    }

在此给大家补充一个点,就是如果我们的bean实现了xxxAware接口,那么这些bean实现的这些接口的方法是在什么时候被调用的。这是在prepareBeanFactory方法中发现的,既然发现了就顺带提一下了。

在prepareBeanFactory方法中发现方法内给bean工厂添加了一个bean后置处理器ApplicationContextAwareProcessor。

beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));

既然这个ApplicationContextAwareProcessor是一个BeanPostProcessor,那么大家如果看懂前面几篇文章应该知道这个ApplicationContextAwareProcessor是在什么时候被调用的了。BeanPostProcessor会在每个bean实例化之后调用初始化方法之前和之后被调用,ApplicationContextAwareProcessor主要实现了其postProcessBeforeInitialization方法,即在调用初始化方法之前完成一些任务。那么ApplicationContextAwareProcessor的任务又是什么呢?处理调用bean实现了Aware接口的方法。

@Override
    public Object postProcessBeforeInitialization(final Object bean, String beanName) throws BeansException {
        ......
            invokeAwareInterfaces(bean);
        ......
        return bean;
    }

    private void invokeAwareInterfaces(Object bean) {
        if (bean instanceof Aware) {
            if (bean instanceof EnvironmentAware) {
                ((EnvironmentAware) bean).setEnvironment(this.applicationContext.getEnvironment());
            }
            if (bean instanceof EmbeddedValueResolverAware) {
                ((EmbeddedValueResolverAware) bean).setEmbeddedValueResolver(this.embeddedValueResolver);
            }
            if (bean instanceof ResourceLoaderAware) {
                ((ResourceLoaderAware) bean).setResourceLoader(this.applicationContext);
            }
            if (bean instanceof ApplicationEventPublisherAware) {
                ((ApplicationEventPublisherAware) bean).setApplicationEventPublisher(this.applicationContext);
            }
            if (bean instanceof MessageSourceAware) {
                ((MessageSourceAware) bean).setMessageSource(this.applicationContext);
            }
            if (bean instanceof ApplicationContextAware) {
                ((ApplicationContextAware) bean).setApplicationContext(this.applicationContext);
            }
        }
    }

其中我们最熟悉的莫过于ApplicationContextAware了,我们为了能在bean中拿到ApplicationContext就是通过实现ApplicationContextAware接口的。

ConfigurationClassPostProcessor

好了,现在接着分析invokeBeanFactoryPostProcessors方法,因为invokeBeanFactoryPostProcessors方法中调用的BeanFactoryPostProcessors,我记得在第一篇分析spring源码的文章中提到过这个BeanFactoryPostProcessors,就是在bean工厂准备好之后调用的处理器。

ConfigurationClassPostProcessor是实现了BeanDefinitionRegistryPostProcessor接口的,而BeanDefinitionRegistryPostProcessor接口又是继承BeanFactoryPostProcessors接口的。

invokeBeanFactoryPostProcessors方法最后调用了PostProcessorRegistrationDelegate委托类的静态方法invokeBeanFactoryPostProcessors方法。来看下这个方法。

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

        // 如果有则首先调用 BeanDefinitionRegistryPostProcessors ,
        // BeanDefinitionRegistryPostProcessors是继承BeanFactoryPostProcessor的接口
        Set<String> processedBeans = new HashSet<String>();

        //如果bean工厂实现了BeanDefinitionRegistry接口,
        //这里的bean工厂就是DefaultListableBeanFactory
        if (beanFactory instanceof BeanDefinitionRegistry) {
            BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory;

            List<BeanDefinitionRegistryPostProcessor> registryProcessors = new LinkedList<BeanDefinitionRegistryPostProcessor>();
            // 此时beanFactoryPostProcessors是空的,因为这个方法是在refresh方法中被调用的,而refresh方法之前我们并没有注册任何的BeanFactoryPostProcessor
            for (BeanFactoryPostProcessor postProcessor : beanFactoryPostProcessors) {
                ......
            }

            List<BeanDefinitionRegistryPostProcessor> currentRegistryProcessors = new ArrayList<BeanDefinitionRegistryPostProcessor>();

            // 首先调用实现了PriorityOrdered接口的BeanDefinitionRegistryPostProcessors。
            // 获取BeanDefinitionRegistryPostProcessors的bean名称
            String[] postProcessorNames =
                    beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
            for (String ppName : postProcessorNames) {
                //如果是实现了PriorityOrdered接口的,这个PriorityOrdered接口并没有任何方法的定义,只是用来确定优先级的。        
                if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
                    currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
                    processedBeans.add(ppName);
                }
            }
            //排序这些BeanDefinitionRegistryPostProcessors
            sortPostProcessors(currentRegistryProcessors, beanFactory);
            registryProcessors.addAll(currentRegistryProcessors);
            //开始调用这些BeanDefinitionRegistryPostProcessors
            invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
            currentRegistryProcessors.clear();
      ..........
}

通过断点调试发现beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false)获取到的就只有ConfigurationClassPostProcessor这个bean。

图片

接着就是看ConfigurationClassPostProcessor的postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry)方法了。

看懂这个方法就能知道这个ConfigurationClassPostProcessor的作用是什么了。

@Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {
        this.factoriesPostProcessed.add(factoryId);
        if (!this.registriesPostProcessed.contains(factoryId)) {
            processConfigBeanDefinitions((BeanDefinitionRegistry) beanFactory);
        }
        enhanceConfigurationClasses(beanFactory);
        beanFactory.addBeanPostProcessor(new ImportAwareBeanPostProcessor(beanFactory));
    }

    /**
     *  处理注解配置类注册的class
     */
    public void processConfigBeanDefinitions(BeanDefinitionRegistry registry) {
        //用于保存所有被@Configuration注解的类,或者有@Bean注释的方法的类
        List<BeanDefinitionHolder> configCandidates = new ArrayList<BeanDefinitionHolder>();
        //获取当前bean工厂中所有已注册的bean的名称  
        String[] candidateNames = registry.getBeanDefinitionNames();

        for (String beanName : candidateNames) {
            BeanDefinition beanDef = registry.getBeanDefinition(beanName);
            //如果这个bean是被@Configuration注释的bean,或者这个bean中有被@Bean方法注释的方法。
            if (ConfigurationClassUtils.checkConfigurationClassCandidate(beanDef, this.metadataReaderFactory)) {
                configCandidates.add(new BeanDefinitionHolder(beanDef, beanName));
            }
        }
        ......

        // 解析每个@Configuration类
        ConfigurationClassParser parser = new ConfigurationClassParser(
                this.metadataReaderFactory, this.problemReporter, this.environment,
                this.resourceLoader, this.componentScanBeanNameGenerator, registry);

        //使用当前configCandidates构造一个新的集合
        Set<BeanDefinitionHolder> candidates = new LinkedHashSet<BeanDefinitionHolder>(configCandidates);
        Set<ConfigurationClass> alreadyParsed = new HashSet<ConfigurationClass>(configCandidates.size());
        do {
            // candidates中存放的是所有配置类,解析candidates中的配置类。
            // 这个方法我们需要重点关注,下面会分析
            parser.parse(candidates);
            parser.validate();

            // parser.getConfigurationClasses()获取当前解析出来(包括在此之前的)的所有的配置类。
            Set<ConfigurationClass> configClasses = new LinkedHashSet<ConfigurationClass>(parser.getConfigurationClasses());
            // 移除已经解析过的配置类
            configClasses.removeAll(alreadyParsed);

            // this.reader是一个ConfigurationClassBeanDefinitionReader
            this.reader.loadBeanDefinitions(configClasses);
            // 将当前配置类设置为已经解析。
            alreadyParsed.addAll(configClasses);
            //清空当前配置类解析出来的所有bean定义
            candidates.clear();
            ......
            //candidates又存放了当前被解析出来的bean定义中有被@Configuration注释的类
        }while (!candidates.isEmpty());
        ......
    }

所以配置类中@Import、@ComponentScans以及@Bean注释的方法都是在这里被处理的,如果被@Configuration注释的配置类中使用了@Import导入了其它配置了,那么这个do{}while()就是处理@Import导入的其它配置了的,广度优先遍历直到所有的配置类都已经被处理完成,这样整合spring容器就初始化完成了。我们先继续深入查看ConfigurationClassParser的parse方法。

ConfigurationClassParser的parse方法->

processConfigurationClass方法。

protected final SourceClass doProcessConfigurationClass(ConfigurationClass configClass, SourceClass sourceClass)
            throws IOException {

        // 先递归地处理任何成员(嵌套)类
        processMemberClasses(configClass, sourceClass);

        // 处理任何@PropertySource注解
        for (AnnotationAttributes propertySource : AnnotationConfigUtils.attributesForRepeatable(
                sourceClass.getMetadata(), PropertySources.class,
                org.springframework.context.annotation.PropertySource.class)) {

        }

        // 处理任何@ComponentScan注解(包括@ComponentScans)
        Set<AnnotationAttributes> componentScans = AnnotationConfigUtils.attributesForRepeatable(
                sourceClass.getMetadata(), ComponentScans.class, ComponentScan.class);
        if (!componentScans.isEmpty() &&
                !this.conditionEvaluator.shouldSkip(sourceClass.getMetadata(), ConfigurationPhase.REGISTER_BEAN)) {

        }

        // 处理@Import注解
        processImports(configClass, sourceClass, getImports(sourceClass), true);

        // 处理任何@ImportResource注解
        if (sourceClass.getMetadata().isAnnotated(ImportResource.class.getName())) {
        }

        // 处理@Bean注解的方法
        Set<MethodMetadata> beanMethods = retrieveBeanMethodMetadata(sourceClass);
        for (MethodMetadata methodMetadata : beanMethods) {
        }

        // 处理接口上的默认方法
        processInterfaces(configClass, sourceClass);
        ......
        return null;
    }

我已经去掉了具体的处理代码,直接给出processConfigurationClass方法处理配置类的内容而已,提供个思路给你自己去看。

好了,到这里已经可以明确直到这个ConfigurationClassPostProcessor处理器的作用了,文章也很长了,所以下面我只介绍剩下几个Processor是在什么时候被调用的,具体这个Processor的作用是什么就靠看观自己去发现了。

registerBeanPostProcessors方法

继续分析refresh方法。在invokeBeanFactoryPostProcessors方法之后就是registerBeanPostProcessors方法。而registerBeanPostProcessors方法最终是调用PostProcessorRegistrationDelegate类的静态方法registerBeanPostProcessors。

图片

所以

AutowiredAnnotationBeanPostProcessor
RequiredAnnotationBeanPostProcessor
CommonAnnotationBeanPostProcessor

是在registerBeanPostProcessors方法中被调用的,在ConfigurationClassPostProcessor被调用完成之后,也就是在处理完所有bean的注册之后调用。这几个处理器可以根据其类型名称猜测其功能,如Autowired处理自动装配。

@by~ 就介绍到这里了,我觉得贴一堆代码出来也没有任何意义,还不如自己直接去看源码呢,所以我只提供个思路,具体更详细的功能实现就需要大伙自己去看源码了。

#后端

声明:公众号、CSDN、掘金的曾用名:“Java艺术”,因此您可能看到一些早期的文章的图片有“Java艺术”的水印。

文章推荐

Redis数据持久化策略

我们可以通过修改redis.conf配置文件来选择使用持久化策略,redis提供了三种持久化策略:RDB快照、AOF(Append-only file)、混合策略。

ConcurrentHashMap是如何实现线程安全的

ConcurrentHashMap 在1.7中 实现线程安全是通过锁住Segment对象的。而在1.8 中则是针对首个节点(table[hash(key)]取得的链接或红黑树的首个节点)进行加锁操作。

Spring源码分析ioc容器总结篇

这篇文章是对前面几篇文章做一个小节,本篇不写一行代码,单纯的文字总结。

Spring源码分析(二)bean的创建过程

上一篇有说到过BeanDefinition,主要关注的是其扩展接口AnnotateBeanDefinition和其子类AnnotateGenericBeanDefinition。本篇先超前介绍spring是如果通过BeanDefinition来创建一个bean的。

Spring源码分析(一)理解一些类及接口

本篇主要介绍一些重要的接口及类,下一篇介绍bean的创建过程,接着介绍AnnotationConfigApplicationContext的初始化流程,最后一篇通过源码总结bean的生命周期。

Spring源码分析(三)registerBean方法分析

介绍AnnotationConfigApplicationContext工作流程,本篇先介绍registerBean方法内部执行流程分析。