Spring 5.x Source ten invokeBeanFactoryPostProcessors three tour

BeanFactoryPostProcessor execution processor

Speaking in front of a method to deal with BeanDefinitionRegistryPostProcessor interface, after the treatment is over now to start treatment BeanFactoryPostProcessor interface, and also the first BeanDefinitionRegistryPostProcessortype of treatment, followed by a custom BeanFactoryPostProcessortype of processing.

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

Type of processor execution BeanDefinitionRegistryPostProcessor

Mainly ConfigurationClassPostProcessorof postProcessBeanFactory, there is the custom, our main concern ConfigurationClassPostProcessoris.

	private static void invokeBeanFactoryPostProcessors(
			Collection<? extends BeanFactoryPostProcessor> postProcessors, ConfigurableListableBeanFactory beanFactory) {

		for (BeanFactoryPostProcessor postProcessor : postProcessors) {
			postProcessor.postProcessBeanFactory(beanFactory);
		}
	}

ConfigurationClassPostProcessor的postProcessBeanFactory

Enhanced configuration class is doing, and then add a ImportAwareBeanPostProcessorpost-processor.

@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 the defined configuration bean extract enhanceConfigurationClasses

First, the configuration will first beandefine it are acquired, according to ConfigurationClassUtils.CONFIGURATION_CLASS_ATTRIBUTEattributes will be set if the class is a configuration attribute fullor lite. Here we must note that if in front of a custom BeanDefinitionRegistryPostProcessorextension is created, it would create the configuration classes, where there will be a prompt.

		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 of enhanceConfigurationClasses enhanced

Create a configuration class booster ConfigurationClassEnhancer, will traverse the configuration beandefinition of the agent to obtain the target class, and then the agent to enhance, return the proxy class, and then beandefine the BeanClasssettings for the proxy class, this time behind the creation of the proxy class is created.

		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 of enhancer enhancement

First determine the target class is not a EnhancedConfigurationtype, and if so explanation has been enhanced too, because springwith CGLIBinherit enhanced when the target class, implement EnhancedConfigurationthe interface, is actually BeanFactoryAwarethe interface. If it had not enhanced newEnhancerto create a booster, and then createClasscreate an enhanced class.

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 of newEnhancer create intensifier

This is CGLIBa booster, to set the parent class, set the interface, which is EnhancedConfigurationthen set generation strategy, set up a filter.

	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 filter

In fact, some of the interceptor, the method used to do to intercept, thereby enhanced.

	private static final Callback[] CALLBACKS = new Callback[] {
			new BeanMethodInterceptor(),
			new BeanFactoryAwareMethodInterceptor(),
			NoOp.INSTANCE
	};
	private static final ConditionalCallbackFilter CALLBACK_FILTER = new ConditionalCallbackFilter(CALLBACKS);
BeanFactoryAwareGeneratorStrategy generation strategy

It is how to generate bytecode files to see their own extensions to the generated proxy class, such as he is, this will generate a property $$beanFactory, and then use the method in which the interceptor.
Here Insert Picture Description
In fact, it is to make springthe beanFactoryparticipatory approach configuration class of the implementation process, specifically goes on to say that what's the use.

ConfigurationClassEnhancer of createClass create a proxy class

Create a proxy class, without creating instances, and then register the filter, which is a CGLIBprocess of generating complex bytecode.

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

We can see the middle of a process he generated beanFactorybytecode attributes:
Here Insert Picture Description
the latter get one of our own to simulate springhow use cglibto generate dynamic proxy it.

Well, here today, we hope to help study and understand, do not spray the Great God see, understand only their own learning, limited capacity, please excuse.

Published 235 original articles · won praise 74 · views 30000 +

Guess you like

Origin blog.csdn.net/wangwei19871103/article/details/105008498