Spring 5.x 源码之旅-9invokeBeanFactoryPostProcessors二

作者简介:大家好,我是smart哥,前中兴通讯、美团架构师,现某互联网公司CTO

联系qq:184480602,加我进群,大家一起学习,一起进步,一起对抗互联网寒冬

学习必须往深处挖,挖的越深,基础越扎实!

阶段1、深入多线程

阶段2、深入多线程设计模式

阶段3、深入juc源码解析


阶段4、深入jdk其余源码解析


阶段5、深入jvm源码解析

码哥源码部分

码哥讲源码-原理源码篇【2024年最新大厂关于线程池使用的场景题】

码哥讲源码【炸雷啦!炸雷啦!黄光头他终于跑路啦!】

码哥讲源码-【jvm课程前置知识及c/c++调试环境搭建】

​​​​​​码哥讲源码-原理源码篇【揭秘join方法的唤醒本质上决定于jvm的底层析构函数】

码哥源码-原理源码篇【Doug Lea为什么要将成员变量赋值给局部变量后再操作?】

码哥讲源码【你水不是你的错,但是你胡说八道就是你不对了!】

码哥讲源码【谁再说Spring不支持多线程事务,你给我抽他!】

终结B站没人能讲清楚红黑树的历史,不服等你来踢馆!

打脸系列【020-3小时讲解MESI协议和volatile之间的关系,那些将x86下的验证结果当作最终结果的水货们请闭嘴】

ConfigurationClassParser加载bean定义还有一点尾巴

循环解析加载bean定义

上一篇讲了是一次解析加载bean定义的过程,其实外面是个循环,因为你加载了bean定义后,可能会有新的配置类的bean定义,所以也要进行解析和加载bean,因此是一个循环。我省略了部分代码,把主要的循环流程和判断留下来了。其实就是循环处理新加载进来的配置类的bean定义,直到没有为止。

    		do {//开始解析configCandidates元素
    			parser.parse(candidates);//解析配置类集合
    			parser.validate();//验证如果要CGLIB代理的话,条件是否满足,比如类不能final,bean注解		
    			this.reader.loadBeanDefinitions(configClasses);//加载bean定义
    			...
    			if (registry.getBeanDefinitionCount() > candidateNames.length) {//如果有加载到新的bean定义,再继续加载
    				...
    				for (String candidateName : newCandidateNames) {
    					if (!oldCandidateNames.contains(candidateName)) {//处理新的
    						BeanDefinition bd = registry.getBeanDefinition(candidateName);
    						if (ConfigurationClassUtils.checkConfigurationClassCandidate(bd, this.metadataReaderFactory) &&
    								!alreadyParsedClasses.contains(bd.getBeanClassName())) {//符合配置类要求就添加到candidates
    							candidates.add(new BeanDefinitionHolder(bd, candidateName));
    						}
    					}
    				}
    				candidateNames = newCandidateNames;//更新候选名字
    			}
    		}
    		while (!candidates.isEmpty());

注册单例importStack

importStack注册为单例,为了支持ImportAware接口扩展,说明已经处理Import注解过了。

    if (sbr != null && !sbr.containsSingleton(IMPORT_REGISTRY_BEAN_NAME)) {
    			sbr.registerSingleton(IMPORT_REGISTRY_BEAN_NAME, parser.getImportRegistry());
    		}

清除字节码元数据缓存

有些bean定义的元数据是通过URL加载字节码文件解析来的,为了避免每次都去IO操作,会有元数据的缓存,现在处理完了就要把缓存清除了。

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

BeanDefinitionRegistryPostProcessor后置处理器处理流程

处理一般排序的BeanDefinitionRegistryPostProcessor后置处理器

至此ConfigurationClassPostProcessor的处理完成了,也就是有优先级PriorityOrdered的后置处理器处理好了,现在要处理一般顺序Ordered的处理器了,这段代码跟前面的一样,只是这次是取一般顺序的处理器,执行的是一样的流程,这里还是再次获取BeanDefinitionRegistryPostProcessor类型的,会把所有的都获取出来,当然包括处理过的,不过没关系,处理过的处理器会放入processedBeans中,不会再次处理的:

    //再次获取没处理过的BeanDefinitionRegistryPostProcessors且实现Ordered接口的来处理,因为可能前面处理后产生新的bean定义
    postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
    			for (String ppName : postProcessorNames) {
    				//没处理过的,而且是Ordered类型的
    				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);

其实这里也可能是PriorityOrdered类型的,是通过前面解析出来的。比如我们来看这个扩展点。

扩展点实战一

比如创建了一个TestBeanDefinitionRegistryPostProcessorPriorityOrdered 实现了BeanDefinitionRegistryPostProcessorOrdered 。

    public class TestBeanDefinitionRegistryPostProcessorPriorityOrdered implements BeanDefinitionRegistryPostProcessor, PriorityOrdered {
        public TestBeanDefinitionRegistryPostProcessorPriorityOrdered(){
            System.out.println("TestBeanDefinitionRegistryPostProcessorPriorityOrdered被创建了");
        }
    
        @Override
        public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
            System.out.println("MyBeanDefinitionRegistryPostProcessorPriorityOrdered postProcessBeanDefinitionRegistry");
        }
    
        @Override
        public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
            System.out.println("MyBeanDefinitionRegistryPostProcessorPriorityOrdered postProcessBeanFactory");
        }
        //排序的值,越小越前面
        @Override
        public int getOrder() {
            return 1;
        }
    }

然后配置类里面用bean注解方法,直接返回这个实例类型,我这里为了方便,其实应该返回接口类型,另外写一个接口类型比较好的。

    @Configuration
    public class MyConfig {
        @Bean
        public TestBeanDefinitionRegistryPostProcessorPriorityOrdered myRegistrar(){
            return  new TestBeanDefinitionRegistryPostProcessorPriorityOrdered();
        }
    }

执行的结果就是会被创建出来,然后执行postProcessBeanDefinitionRegistry方法:

注意

这里要注意,这个时候因为要创建TestBeanDefinitionRegistryPostProcessorPriorityOrdered处理器,所以MyConfig也会被创建出来,作为单例。

循环处理最后剩下的BeanDefinitionRegistryPostProcessor后置处理器

最后就处理剩下的那些后置处理器,比如我在前面的扩展点再注册bean定义。

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

扩展点实战二

还是刚才的TestBeanDefinitionRegistryPostProcessorPriorityOrdered ,我在postProcessBeanDefinitionRegistry里自定义注册了一个bean定义TestBeanDefinitionRegistryPostProcessor
他就会在最后被getBeanNamesForType找到执行。

    public class TestBeanDefinitionRegistryPostProcessorPriorityOrdered implements BeanDefinitionRegistryPostProcessor, PriorityOrdered {
        public TestBeanDefinitionRegistryPostProcessorPriorityOrdered() {
            System.out.println("TestBeanDefinitionRegistryPostProcessorPriorityOrdered被创建了");
        }
    
    
        @Override
        public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
            System.out.println("MyBeanDefinitionRegistryPostProcessorPriorityOrdered postProcessBeanDefinitionRegistry");
            AnnotatedBeanDefinition genericBeanDefinition=new AnnotatedGenericBeanDefinition(TestBeanDefinitionRegistryPostProcessor.class);
            registry.registerBeanDefinition("TestBeanDefinitionRegistryPostProcessor",genericBeanDefinition);
    
        }
    
        @Override
        public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
            System.out.println("MyBeanDefinitionRegistryPostProcessorPriorityOrdered postProcessBeanFactory");
        }
    
        //排序的值,越小越前面
        @Override
        public int getOrder() {
            return 1;
        }
    }

TestBeanDefinitionRegistryPostProcessor 也是BeanDefinitionRegistryPostProcessor 类型的,扩展方法里又注册了一个UserDaoImple

    public class TestBeanDefinitionRegistryPostProcessor implements BeanDefinitionRegistryPostProcessor {
        @Override
        public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
            System.out.println("MyBeanDefinitionRegistryPostProcessor postProcessBeanDefinitionRegistry");
            registry.registerBeanDefinition("UserDaoImple",new AnnotatedGenericBeanDefinition(UserDaoImple.class));
        }
    
        @Override
        public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
            System.out.println("MyBeanDefinitionRegistryPostProcessor postProcessBeanFactory");
        }
    }

结果:


而且在里面又注册了一个UserDaoImple


至此,所有实现的BeanDefinitionRegistryPostProcessor接口的处理器都处理完成了。
我们的自定义扩展顺序可以看这里:

扩展点顺序

ConfigurationClassPostProcessor处理MyConfigMyConfig定义了TestBeanDefinitionRegistryPostProcessorPriorityOrderedbean注解方法,可以被加载进bean定义。


TestBeanDefinitionRegistryPostProcessorPriorityOrderedpostProcessBeanDefinitionRegistry方法中注册了TestBeanDefinitionRegistryPostProcessorbean定义。


TestBeanDefinitionRegistryPostProcessor中的postProcessBeanDefinitionRegistry又注册了UserDaoImplebean定义。

注意

这个时候你会发现创建处理器的同时把配置类也创建了。

至此BeanDefinitionRegistryPostProcessor的处理器全部处理完成,包括自定义的。后面就要处理BeanFactoryPostProcessor的处理器啦,这个后面讲。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值