Spring 5.x 源码之旅-10invokeBeanFactoryPostProcessors三

作者简介:大家好,我是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下的验证结果当作最终结果的水货们请闭嘴】

执行BeanFactoryPostProcessor处理器

前面讲的是先处理BeanDefinitionRegistryPostProcessor接口的方法,处理完了之后现在要开始处理BeanFactoryPostProcessor接口的方法了,也是先BeanDefinitionRegistryPostProcessor类型处理,然后是自定义的BeanFactoryPostProcessor类型的处理。

    invokeBeanFactoryPostProcessors(registryProcessors, beanFactory);//BeanDefinitionRegistryPostProcessor的
    invokeBeanFactoryPostProcessors(regularPostProcessors, beanFactory);//自定义的BeanFactoryPostProcessor

执行BeanDefinitionRegistryPostProcessor类型的处理器

主要就是ConfigurationClassPostProcessorpostProcessBeanFactory,还有就是自定义的,我们主要关注ConfigurationClassPostProcessor的。

    	private static void invokeBeanFactoryPostProcessors(
    			Collection<? extends BeanFactoryPostProcessor> postProcessors, ConfigurableListableBeanFactory beanFactory) {
    
    		for (BeanFactoryPostProcessor postProcessor : postProcessors) {
    			postProcessor.postProcessBeanFactory(beanFactory);
    		}
    	}

ConfigurationClassPostProcessor的postProcessBeanFactory

主要是做配置类的增强,然后添加一个ImportAwareBeanPostProcessor后置处理器。

    @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);
    		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));//添加后置处理器
    	}

ConfigurationClassPostProcessor的enhanceConfigurationClasses提取出配置bean定义

首先会先把配置bean定义都获取出来,根据ConfigurationClassUtils.CONFIGURATION_CLASS_ATTRIBUTE属性,如果是配置类会设置属性full或者lite。这里要注意,如果前面有自定义的BeanDefinitionRegistryPostProcessor扩展被创建出来的话,也会创建配置类,这里就会有个提示。

    		Map<String, AbstractBeanDefinition> configBeanDefs = new LinkedHashMap<>();
    		for (String beanName : beanFactory.getBeanDefinitionNames()) {
    			BeanDefinition beanDef = beanFactory.getBeanDefinition(beanName);
    			Object configClassAttr = beanDef.getAttribute(ConfigurationClassUtils.CONFIGURATION_CLASS_ATTRIBUTE);//获取配置属性
    			MethodMetadata methodMetadata = null;
    			if (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;
    				if (!abd.hasBeanClass()) {
    					try {//bean注解的方法设置类加载器
    						abd.resolveBeanClass(this.beanClassLoader);
    					}
    					catch (Throwable ex) {
    						throw new IllegalStateException(
    								"Cannot load configuration class: " + beanDef.getBeanClassName(), ex);
    					}
    				}
    			}//这里就是前面的full 跟 lite的用处了,full可以做增强
    			if (ConfigurationClassUtils.CONFIGURATION_CLASS_FULL.equals(configClassAttr)) {
    				if (!(beanDef instanceof AbstractBeanDefinition)) {
    					throw new BeanDefinitionStoreException("Cannot enhance @Configuration bean definition '" +
    							beanName + "' since it is not stored in an AbstractBeanDefinition subclass");
    				}//已经存在单例了,就不能增强了
    				else if (logger.isInfoEnabled() && beanFactory.containsSingleton(beanName)) {
    					logger.info("Cannot enhance @Configuration bean definition '" + beanName +
    							"' 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);
    			}
    		}
    		if (configBeanDefs.isEmpty()) {//没有要增强的配置bean直接返回
    			// nothing to enhance -> return immediately
    			return;
    		}

ConfigurationClassPostProcessor的enhanceConfigurationClasses进行增强

先创建一个配置类增强器ConfigurationClassEnhancer ,会遍历配置bean定义,获取代理的目标类,然后进行代理增强,返回代理类,然后把bean定义的BeanClass设置为代理类,这样后面创建的时候就会创建代理类。

    		ConfigurationClassEnhancer enhancer = new 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, this.beanClassLoader);//进行代理
    			if (configClass != enhancedClass) {
    				if (logger.isTraceEnabled()) {
    					logger.trace(String.format("Replacing bean definition '%s' existing class '%s' with " +
    							"enhanced class '%s'", entry.getKey(), configClass.getName(), enhancedClass.getName()));
    				}
    				beanDef.setBeanClass(enhancedClass);//设置为CGLIB动态代理后的类
    			}
    		}
ConfigurationClassEnhancer 的enhancer增强

先判断目标类是不是EnhancedConfiguration类型的,如果是的话说明已经增强过了,因为springCGLIB增强的时候会继承目标类,实现EnhancedConfiguration接口,其实就是BeanFactoryAware接口。如果没有增强过就newEnhancer创建一个增强器,然后createClass创建增强类。

    public Class<?> enhance(Class<?> configClass, @Nullable ClassLoader classLoader) {
    		if (EnhancedConfiguration.class.isAssignableFrom(configClass)) {//如果已经是EnhancedConfiguration,已经被代理过了
    			if (logger.isDebugEnabled()) {
    				logger.debug(String.format("Ignoring request to enhance %s as it has " +
    						"already been enhanced. This usually indicates that more than one " +
    						"ConfigurationClassPostProcessor has been registered (e.g. via " +
    						"<context:annotation-config>). This is harmless, but you may " +
    						"want check your configuration and remove one CCPP if possible",
    						configClass.getName()));
    			}
    			return configClass;
    		}
    		Class<?> enhancedClass = createClass(newEnhancer(configClass, classLoader));//进行动态代理
    		if (logger.isTraceEnabled()) {
    			logger.trace(String.format("Successfully enhanced %s; enhanced class name is: %s",
    					configClass.getName(), enhancedClass.getName()));
    		}
    		return enhancedClass;
    	}
ConfigurationClassEnhancer的newEnhancer创建增强器

这个就是CGLIB的增强器,要设置父类,设置接口,也就是EnhancedConfiguration,然后设置生成策略,设置过滤器。

    	private Enhancer newEnhancer(Class<?> configSuperClass, @Nullable ClassLoader classLoader) {
    		Enhancer enhancer = new Enhancer();
    		enhancer.setSuperclass(configSuperClass);//设置父类
    		enhancer.setInterfaces(new Class<?>[] {EnhancedConfiguration.class});//设置要实现的接口,就是BeanFactoryAware
    		enhancer.setUseFactory(false);
    		enhancer.setNamingPolicy(SpringNamingPolicy.INSTANCE);
    		enhancer.setStrategy(new BeanFactoryAwareGeneratorStrategy(classLoader));//生成策略
    		enhancer.setCallbackFilter(CALLBACK_FILTER);//过滤器拦截器
    		enhancer.setCallbackTypes(CALLBACK_FILTER.getCallbackTypes());//过滤器类型
    		return enhancer;
    	}
CALLBACK_FILTER过滤器

其实就是一些拦截器,用来对方法做拦截,从而进行增强。

    	private static final Callback[] CALLBACKS = new Callback[] {
    			new BeanMethodInterceptor(),
    			new BeanFactoryAwareMethodInterceptor(),
    			NoOp.INSTANCE
    	};
    	private static final ConditionalCallbackFilter CALLBACK_FILTER = new ConditionalCallbackFilter(CALLBACKS);
BeanFactoryAwareGeneratorStrategy生成策略

就是如何生成字节码文件,看自己对生成的代理类做扩展,比如他这个就是会生成一个属性$$beanFactory,然后在方法拦截器里面进行使用。


其实就是让springbeanFactory参与配置类的方法执行过程,具体后面会说这个有什么用。

ConfigurationClassEnhancer的createClass创建代理类

先创建代理类,而不创建实例,然后注册过滤器,里面是CGLIB产生字节码的过程比较复杂。

    	private Class<?> createClass(Enhancer enhancer) {
    		Class<?> subclass = enhancer.createClass();
    		// Registering callbacks statically (as opposed to thread-local)
    		// is critical for usage in an OSGi environment (SPR-5932)...
    		Enhancer.registerStaticCallbacks(subclass, CALLBACKS);//注册回调
    		return subclass;
    	}

我们可以看到中间有个过程他生成了beanFactory属性的字节码:


后面弄一篇我们自己来模拟下spring怎么用cglib生成动态代理的吧。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值