Spring 5.x Source ten invokeBeanFactoryPostProcessors three tour
- BeanFactoryPostProcessor execution processor
- Type of processor execution BeanDefinitionRegistryPostProcessor
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 BeanDefinitionRegistryPostProcessor
type of treatment, followed by a custom BeanFactoryPostProcessor
type of processing.
invokeBeanFactoryPostProcessors(registryProcessors, beanFactory);//BeanDefinitionRegistryPostProcessor的
invokeBeanFactoryPostProcessors(regularPostProcessors, beanFactory);//自定义的BeanFactoryPostProcessor
Type of processor execution BeanDefinitionRegistryPostProcessor
Mainly ConfigurationClassPostProcessor
of postProcessBeanFactory
, there is the custom, our main concern ConfigurationClassPostProcessor
is.
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 ImportAwareBeanPostProcessor
post-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 bean
define it are acquired, according to ConfigurationClassUtils.CONFIGURATION_CLASS_ATTRIBUTE
attributes will be set if the class is a configuration attribute full
or lite
. Here we must note that if in front of a custom BeanDefinitionRegistryPostProcessor
extension 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 bean
definition of the agent to obtain the target class, and then the agent to enhance, return the proxy class, and then bean
define the BeanClass
settings 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 EnhancedConfiguration
type, and if so explanation has been enhanced too, because spring
with CGLIB
inherit enhanced when the target class, implement EnhancedConfiguration
the interface, is actually BeanFactoryAware
the interface. If it had not enhanced newEnhancer
to create a booster, and then createClass
create 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 CGLIB
a booster, to set the parent class, set the interface, which is EnhancedConfiguration
then 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.
In fact, it is to make spring
the beanFactory
participatory 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 CGLIB
process 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 beanFactory
bytecode attributes:
the latter get one of our own to simulate spring
how use cglib
to 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.