• springboot笔记-2-.核心的上下文以及配置扫描解析(上)


    前言

      上一节中简要说明了下springboot自动化配置的关键,那么本节看下springboot真正的初始化过程,如何创建上下文并解析配置,加载我们注册到容器管理中的类。上节已经成功的创建了SpringApplication,那我们就看下其run方法究竟做了些什么

      

    正文

      我们从SpringApplication的run方法开始入手,只看核心代码,其他省略

    public ConfigurableApplicationContext run(String... args) {
            ...//省略代码
            //声明spring上下文
            ConfigurableApplicationContext context = null;
            try {
                ..//省略代码
                //2.新建应用上下文
                context = createApplicationContext();
                ..//省略代码
                //3.刷新上下文
                refreshContext(context);
                //4.完成刷新上下文后调用(目前空白)
                afterRefresh(context, applicationArguments);
                ..//省略代码
            }
            
            return context;
        }

      通过上面我们可以发现,run方法核心步骤就是创建ApplicatonContext,这儿主要的步骤有两个 1.创建应用上下文 2.刷新上下文。我们从创建开始看

    1.创建spring的核心 ApplicationContext

      查看createApplicationContext方法

    public static final String DEFAULT_WEB_CONTEXT_CLASS = "org.springframework.boot."
                + "web.servlet.context.AnnotationConfigServletWebServerApplicationContext";
    protected ConfigurableApplicationContext createApplicationContext() {
        Class<?> contextClass = this.applicationContextClass;
        if (contextClass == null) {
            try {
                switch (this.webApplicationType) {
                case SERVLET:
                    //我们使用这个    
                    contextClass = Class.forName(DEFAULT_WEB_CONTEXT_CLASS);
                    break;
                case REACTIVE:
                    contextClass = Class.forName(DEFAULT_REACTIVE_WEB_CONTEXT_CLASS);
                    break;
                default:
                    contextClass = Class.forName(DEFAULT_CONTEXT_CLASS);
                }
            }
            ..//省略
        }
        //反射生成实例
        return (ConfigurableApplicationContext) BeanUtils.instantiateClass(contextClass);
    }

      这儿其实看着是很简单的逻辑,就是根据类型,选择与一个合适的创建,这儿我们就用常见的servlet来说明。servlet对应的上下文为AnnotationConfigServletWebServerApplicationContext。然后最后会根据反射来生成一个实例并返回。我们可以看下这个上下文的类图

       相信这个类继承结构大家都看着比较头痛,毕竟作为核心类。这儿就挑两个个重要的说下。

      第一。  其最终实现了BeanFactory接口,并继承了GenericApplicationContext。并且我们查看其构造函数会传入一个BeanFactory

        public AnnotationConfigServletWebServerApplicationContext(DefaultListableBeanFactory beanFactory) {
            super(beanFactory);
            this.reader = new AnnotatedBeanDefinitionReader(this);
            this.scanner = new ClassPathBeanDefinitionScanner(this);
        }

      最终在GenericApplicationContext中有如下代码

    private final DefaultListableBeanFactory beanFactory;
    
    public GenericApplicationContext() {
        this.beanFactory = new DefaultListableBeanFactory();
    }
    
    public GenericApplicationContext(DefaultListableBeanFactory beanFactory) {
        Assert.notNull(beanFactory, "BeanFactory must not be null");
        this.beanFactory = beanFactory;
    }

      会发现上下文不论如何都会持有一个beanFactory,很多人被问到过ApplicationContext和beanFactory的区别与联系。其实这儿就能看出来是一个很典型的静态代理的案例。既然是代理,就说明了肯定ApplicationContext在保持Beanfactory的原有功能时又扩展了很多功能。这样就可以做到既兼容旧版本,又增强很多功能。当然了,具体的区别有兴趣的可以去看下二者的源代码。

      

      第二。我们在AnnotationConfigServletWebServerApplicationContext的构造函数中发现了有如下步骤 

    this.reader = new AnnotatedBeanDefinitionReader(this);

      这儿新建了一个注解bean的解析器。我们一路跟着源码看下

        public AnnotatedBeanDefinitionReader(BeanDefinitionRegistry registry, Environment environment) {
            Assert.notNull(registry, "BeanDefinitionRegistry must not be null");
            Assert.notNull(environment, "Environment must not be null");
            this.registry = registry;
            this.conditionEvaluator = new ConditionEvaluator(registry, environment, null);
            AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry);
        }

      这儿我们会发现该方法最后会为registry注册一些解析器,我们看下AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry);该方法会为Beanfactory设置一系列的BeanDefinition,以及其他的一些东西,

    public static Set<BeanDefinitionHolder> registerAnnotationConfigProcessors(
            BeanDefinitionRegistry registry, @Nullable Object source) {
    
        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);
    
        // 处理@Configuration @ComponentScans  @Component  @Bean等注解  @PropertySources  @ImportResource  等
        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));
        }
        // 处理 @Autowired  @Value 等
        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));
        }
        // 处理@Required @
        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));
        }
    
        // 处理类似@PostConstruct 和@PreDestroy
        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的话这里有处理的  例如@Selevt
        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));
        }
        // 处理类似@EventListener的注解
        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;
    }

      可以发现这儿设置了很多BeanDefinition,尤其是是ConfigurationClassPostProcessor,AutowiredAnnotationBeanPostProcessor这两可以说是相当核心的两个后置处理器,在后面spring进行配置解析的时候会相当的有用。

      

      到此,创建ApplicationContext就完成了,我们看系统刷新上下文的时候做了些什么

    2. refreshContext  spring的核心加载方法

      该方法可以说占据了springboot启动的绝大部分时间,也是springboot启动中最为核心的方法。

      

        private void refreshContext(ConfigurableApplicationContext context) {
            refresh(context);
            if (this.registerShutdownHook) {
                try {
                    context.registerShutdownHook();
                }
                catch (AccessControlException ex) {
                    // Not allowed in some environments.
                }
            }
        }

      

        protected void refresh(ApplicationContext applicationContext) {
            Assert.isInstanceOf(AbstractApplicationContext.class, applicationContext);
            ((AbstractApplicationContext) applicationContext).refresh();
        }

      跟着代码一路走,发现其最终调用的是上下文的refresh方法。由于其被强转为AbstractApplicationContext,所以我们直接看其refresh方法,到此就进入ApplicationContext类中了。

    3.ApplicationContext中refresh方法

      该方法里面有很多初始化方法,我们也选择核心的说明

    @Override
    public void refresh() throws BeansException, IllegalStateException {
        synchronized (this.startupShutdownMonitor) {
            //初始化之前的一些准备,例如设置开始标记等
            prepareRefresh();
    
            // 获取到上面提到的beanFactory
            ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
    
            // 初始注册一些要用到的类
            prepareBeanFactory(beanFactory);
    
            try {
                // 添加一些BeanFactory的postProcess
                postProcessBeanFactory(beanFactory);
    
                // 执行BeanFactory的PostProcessors
                invokeBeanFactoryPostProcessors(beanFactory);
    
                // 注册一些BeanPostProcessors
                registerBeanPostProcessors(beanFactory);
    
                ../略过
                
                // 一些特殊的操作,例如
                //本案例中是AnnotationConfigServletWebServerApplicationContext 那么这儿会开始创建servlet容器
                onRefresh();
    
                ../略过
    
                // 实例化容器中未设置懒加载的类
                finishBeanFactoryInitialization(beanFactory);
                
                ../略过
            }
    
        }
    }

      这儿我们我们主要看两个方法   一是invokeBeanFactoryPostProcessors,该方法会找出所有需要加载的bean。然后是finishBeanFactoryInitialization方法,该方法会将需要加载的bean进行实例化并装载属性。

    4.invokeBeanFactoryPostProcessors方法

      该方法我们跟着源代码走,最终会走到PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors方法,由于该方法过长。所以我们分段说明

    4.1 无所不在的PostProcesser

      不得不说spring将切面应用到了极致啊。。基本每初始化某个东西都会有其对应的PostProcessor,虽然看着略显繁琐,但是却极大的增加了我们的扩展点

    public static void invokeBeanFactoryPostProcessors(
                ConfigurableListableBeanFactory beanFactory, List<BeanFactoryPostProcessor> beanFactoryPostProcessors) {
    
            // Invoke BeanDefinitionRegistryPostProcessors first, if any.
            Set<String> processedBeans = new HashSet<>();
    
            if (beanFactory instanceof BeanDefinitionRegistry) {
                //将我们的BeanFactory强转为BeanDefinitionRegistry
                BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory;
                List<BeanFactoryPostProcessor> regularPostProcessors = new LinkedList<>();
                List<BeanDefinitionRegistryPostProcessor> registryProcessors = new LinkedList<>();
                //循环我们传入的BeanFactoryPostProcessor  如果其是BeanDefinitionRegistryPostProcessor  
                //那么这儿执行其postProcessBeanDefinitionRegistry方法
                for (BeanFactoryPostProcessor postProcessor : beanFactoryPostProcessors) {
                    if (postProcessor instanceof BeanDefinitionRegistryPostProcessor) {
                        BeanDefinitionRegistryPostProcessor registryProcessor =
                                (BeanDefinitionRegistryPostProcessor) postProcessor;
                        registryProcessor.postProcessBeanDefinitionRegistry(registry);
                        registryProcessors.add(registryProcessor);
                    }
                    else {
                        regularPostProcessors.add(postProcessor);
                    }
                }

       上述代码也是执行了传入的Proccessor类型为BeanDefinitionRegistryPostProcessor的postProcessBeanDefinitionRegistry方法。

    4.2 第一级BeanDefinitionRegistryPostProcessor执行(即实现了PriorityOrdered接口)

     

    List<BeanDefinitionRegistryPostProcessor> currentRegistryProcessors = new ArrayList<>();
    
    // 找到系统所有实现了PriorityOrdered接口的BeanDefinitionRegistryPostProcessor接口实现类
    // 这儿会找到我们刚刚的
    ConfigurationClassPostProcessor

    String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false); for (String ppName : postProcessorNames) { if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) { currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class)); processedBeans.add(ppName); } } //排序 sortPostProcessors(currentRegistryProcessors, beanFactory); //将刚找到的BeanDefinitionRegistryPostProcessor加入registryProcessors registryProcessors.addAll(currentRegistryProcessors); //执行刚找到的BeanDefinitionRegistryPostProcessor invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry); //清空 currentRegistryProcessors.clear();

      这儿即找实现了BeanDefinitionRegistryPostProcessor,PriorityOrdered的类。而我们在第一节中最后提到的ConfigurationClassPostProcessor刚好是满足的,我们可以在回顾一下

       这儿我们进入invokeBeanDefinitionRegistryPostProcessors方法看下

        private static void invokeBeanDefinitionRegistryPostProcessors(
                Collection<? extends BeanDefinitionRegistryPostProcessor> postProcessors, BeanDefinitionRegistry registry) {
    
            for (BeanDefinitionRegistryPostProcessor postProcessor : postProcessors) {
                postProcessor.postProcessBeanDefinitionRegistry(registry);
            }
        }

      可以看到是迭代所有BeanDefinitionRegistryPostProcessor并执行其postProcessBeanDefinitionRegistry方法。而上面说到我们会拿到ConfigurationClassPostProcessor,所以这儿我们直接看ConfigurationClassPostProcessor的方法,由于该方法是spring进行配置解析的重中之重,所以篇幅较长

    4.2.1 校验并为本次解析设置id,防止重复加载

       第一步则是设置了本次解析的id,防止重复解析

    public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) {
        //得到registry的hash码作为id
        int registryId = System.identityHashCode(registry);
        //校验id
        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);
    }

    4.2.2 正式解析

      这儿我们依旧一段一段的看

      

    List<BeanDefinitionHolder> configCandidates = new ArrayList<>();
    //找到该registry所有的candidateNames  也就是我们第一步结尾添加的那些
    String[] candidateNames = registry.getBeanDefinitionNames();
    
    for (String beanName : candidateNames) {
        BeanDefinition beanDef = registry.getBeanDefinition(beanName);
        //isFullConfigurationClass 判断是否是带有@Configuration  
        //isLiteConfigurationClass 判断是否带有@Component,@ComponentScan,@Import,@ImportResource,@Bean 5个注解中的任一个
        // 具体可以查看 https://blog.csdn.net/u011624903/article/details/102564491
        if (ConfigurationClassUtils.isFullConfigurationClass(beanDef) ||
                ConfigurationClassUtils.isLiteConfigurationClass(beanDef)) {
            if (logger.isDebugEnabled()) {
                logger.debug("Bean definition has already been processed as a configuration class: " + beanDef);
            }
        }
        // 这儿由于我们的主启动类中@SpringbootApplication带@Configuration注解 所以主类满足
        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;
    }
    // 排序
    configCandidates.sort((bd1, bd2) -> {
    int i1 = ConfigurationClassUtils.getOrder(bd1.getBeanDefinition());
    int i2 = ConfigurationClassUtils.getOrder(bd2.getBeanDefinition());
    return Integer.compare(i1, i2);
    });
     

      这儿会将BeanFactory中已经存在的BeanDefinitionName全部查出来并获取其BeanDefinition,由于我们的启动类@SpringbootApplication中已经带有@Configuration  所以这里是满足的(第一节中讲组合注解的时候讲过)

      然后接下来会有查看是否有BeanNameGenerator和environment

    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();
            }

      然后我们就看到了本文最核心的代码了,也就是解析代码。

      我们看下这个解析流程

    // 构建一个ConfigurationClassParser   也就是解析器
    ConfigurationClassParser parser = new ConfigurationClassParser(
            this.metadataReaderFactory, this.problemReporter, this.environment,
            this.resourceLoader, this.componentScanBeanNameGenerator, registry);
    
    //拿到我们解析的配置类  这儿的话是主启动类
    Set<BeanDefinitionHolder> candidates = new LinkedHashSet<>(configCandidates);
    //已经解析的ConfigurationClass集合
    Set<ConfigurationClass> alreadyParsed = new HashSet<>(configCandidates.size());
    do {
        //开始解析
        parser.parse(candidates);
        //验证
        parser.validate();
        //找到本次解析后发现的所有ConfigurationClass
        Set<ConfigurationClass> configClasses = new LinkedHashSet<>(parser.getConfigurationClasses());
        //移除掉已经解析的
        configClasses.removeAll(alreadyParsed);
    
        // 如果没有  则创建一个新的ConfigurationClassBeanDefinitionReader
        if (this.reader == null) {
            this.reader = new ConfigurationClassBeanDefinitionReader(
                    registry, this.sourceExtractor, this.resourceLoader, this.environment,
                    this.importBeanNameGenerator, parser.getImportRegistry());
        }
        //将这些发现的找到本次解析后发现的所有ConfigurationClass再次解析掉
        this.reader.loadBeanDefinitions(configClasses);
        //将其添加到已解析的集合中
        alreadyParsed.addAll(configClasses);
        //清空candidates
        candidates.clear();
        //如果registry中的BeanDefinition数量大于candidateNames  也就是一开始进入方法时的数量
        //即找到的新的需要加入容器的bean了
        if (registry.getBeanDefinitionCount() > candidateNames.length) {
            //拿到所有的已经存在的BeanDefinitionName
            String[] newCandidateNames = registry.getBeanDefinitionNames();
            //初始进来的BeanDefinitionName
            Set<String> oldCandidateNames = new HashSet<>(Arrays.asList(candidateNames));
            //创建已经解析的Class的名字的集合
            Set<String> alreadyParsedClasses = new HashSet<>();
            for (ConfigurationClass configurationClass : alreadyParsed) {
                //将已经解析的添加到集合中
                alreadyParsedClasses.add(configurationClass.getMetadata().getClassName());
            }
            //循环遍历 所有的BeanDefinition  看看有没有configuration被遗漏的
            for (String candidateName : newCandidateNames) {
                //即不是初始化进来时的BeanDefinition
                if (!oldCandidateNames.contains(candidateName)) {
                    //拿到这个BeanDefinition
                    BeanDefinition bd = registry.getBeanDefinition(candidateName);
                    //如果该BeanDefinition也是一个配置类并且没有存在于alreadyParsed  即被遗漏了
                    //那么将其添加到candidates方法 然后再进行
                    if (ConfigurationClassUtils.checkConfigurationClassCandidate(bd, this.metadataReaderFactory) &&
                            !alreadyParsedClasses.contains(bd.getBeanClassName())) {
                        //则再将其添加进去  循环进行解析        
                        candidates.add(new BeanDefinitionHolder(bd, candidateName));
                    }
                }
            }
            candidateNames = newCandidateNames;
        }
    }
    while (!candidates.isEmpty());

      这段代码较长,逻辑还是较为清晰,其实通过这段代码我们就大概明白了springboot进行配置加载的流程了。即根据主启动类进行配置解析,并且将所有遇到的ConfigurationClass全部返回,然后再进行二次解析,最后对所有的BeanDefinition进行校验,如果发现其为ConfigurationClass但是却没有在已解析的集合中,那么久循环一下,再次进行解析

      篇幅有限,具体的解析流程放到下一篇, 解析完第一级BeanDefinitionRegistryPostProcessor后我们开始解析第二级

      

    4.3 第二级BeanDefinitionRegistryPostProcessor(即实现了Ordered接口)

      

                // Next, invoke the BeanDefinitionRegistryPostProcessors that implement Ordered.
                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();

      可以发现其流程和第一级几乎一致,只是增加了一个过滤掉了第一级,所以这儿不讲,如果有自定义的BeanDefinitionRegistryPostProcessor可以测试一下。

    4.4 第三级BeanDefinitionRegistryPostProcessor

      

    // Finally, invoke all other BeanDefinitionRegistryPostProcessors until no further ones appear.
                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();
                }

      处理流程也和前两级几乎一致,这儿也不讲了

    4.4 BeanFactoryPostProcessor的执行

      即找到系统存在的BeanFactoryPostProcessor,同样按照三级的形式根据优先级来执行。具体的逻辑也和上面详细讲的那个一级是一致的。

    String[] postProcessorNames =
                    beanFactory.getBeanNamesForType(BeanFactoryPostProcessor.class, true, false);
    
    //找到所有的BeanFactoryPostProcessor 并根据其级别进行归类
    List<BeanFactoryPostProcessor> priorityOrderedPostProcessors = new ArrayList<>();
    List<String> orderedPostProcessorNames = new ArrayList<>();
    List<String> nonOrderedPostProcessorNames = new ArrayList<>();
    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);
        }
    }
    
    // 执行优先级最高的 即实现了PriorityOrdered接口的
    sortPostProcessors(priorityOrderedPostProcessors, beanFactory);
    invokeBeanFactoryPostProcessors(priorityOrderedPostProcessors, beanFactory);
    
    // 执行第二级的的 即实现了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.
    List<BeanFactoryPostProcessor> nonOrderedPostProcessors = new ArrayList<>();
    for (String postProcessorName : nonOrderedPostProcessorNames) {
        nonOrderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));
    }
    invokeBeanFactoryPostProcessors(nonOrderedPostProcessors, beanFactory);
    //清除缓存
    beanFactory.clearMetadataCache();

      到此,refresh方法中的两个重要方法第一个   invokeBeanFactoryPostProcessors,已经完成,而其中的ConfigurationClassPostProcessor(也就是BeanDefinitionRegistryPostProcessor的一种)负责了最为核心的容器类加载,也就是主要分析的类也分析完成。(详细的类解析过程篇幅问题放在下章)

      

    总结

      本文主要分为了两个部分,创建Spring应用上下文,和执行了其refresh方法中的invokeBeanFactoryPostProcessors方法。

      创建应用上下文的同时也会创建一个DefaultListableBeanFactory,这个也是静态代理的体现。而在执行ApplicationContext的构造函数时,会创建一个AnnotatedBeanDefinitionReader,而这个类中会有一个BeanDefinitionRegistry属性,并将我们一些必须的BeanDefinition添加进去,例如最为核心的  ConfigurationClassPostProcessor也就是在这个时候被添加进去的。

      执行invokeBeanFactoryPostProcessors方法则主要分为三个步骤

    • 执行所有传入的BeanFactoryPostProcessor(如果为BeanFactoryPostProcessor)的postProcessBeanDefinitionRegistry方法

    • 找到BeanFactory中所有的BeanDefinitionRegistryPostProcessor类型的类并按照三级标准执行(实现了PriorityOrdered接口,实现了Ordered接口,啥都没实现 );

    • 找到BeanFactory中所有的BeanFactoryPostProcessor类型的类并按照三级标准执行(实现了PriorityOrdered接口,实现了Ordered接口,啥都没实现 );

      而其第二步则执行了核心的ConfigurationClassPostProcessor,并且是以最优先级执行,该processer会加载系统中所有需要加入容器的类,并且会解析所有的Configuration class

      

      

      

      

  • 相关阅读:
    JS防止刷新,后退,关闭
    IIS日志-网站运维的好帮手
    未能加载文件或程序集“XXX”或它的某一个依赖项。磁盘空间不足---解决方案
    NOPI导出标准格式Excel
    DRBD+Heartbeat+Mysql高可用环境部署
    LVS三种包转发模型调度算法
    nagios环境部署(rhel6.5)
    关于nagios监控
    关于memcached原理及安装部署
    PHP5.4.36 RHEL6.5 源码编译安装
  • 原文地址:https://www.cnblogs.com/hetutu-5238/p/12372276.html
Copyright © 2020-2023  润新知