@Configuration
注解源码如下
其中有一个proxyBeanMethods
属性,就是决定注册到Spring容器中的是原始Bean(Lite模式)还是代理Bean(Full模式)
该属性默认为true,也就是默认是Full模式
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Component
public @interface Configuration {
@AliasFor(annotation = Component.class)
String value() default "";
boolean proxyBeanMethods() default true;
}
具体代码就不演示了,可以自己写两个Class,一个加上@Configuration
,一个加上@Configuration(proxyBeanMethods = false)
然后通过BeanFactory去获取打印观察区别
和@Configuration
的解析处理相关的类是ConfigurationClassPostProcessor
类的部分继承关系如下
public interface BeanDefinitionRegistryPostProcessor extends BeanFactoryPostProcessor {
void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException;
}
public interface BeanFactoryPostProcessor {
void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException;
}
到这里至少知道ConfigurationClassPostProcessor
中要实现上面两个接口的方法
现在就要知道分别是什么时候执行的
直接定位到容器启动处:AbstractApplicationContext#refresh
,核心代码的入口都在这里
然后根据debug,应该在invokeBeanFactoryPostProcessors这个方法中执行两个process方法
@Override
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
// ...
try {
// ...
// Invoke factory processors registered as beans in the context.
invokeBeanFactoryPostProcessors(beanFactory);
// ...
}
}
}
继续跟踪,会在PostProcessorRegistraionDelegate#invokeBeanFactoryPostProcessors
中找到两个方法调用
说明是先执行的postProcessBeanDefinitionRegistry
,再执行postProcessBeanFactory
这时回头看ConfigurationClassPostProcessor
中的两个方法
先看postProcessBeanDefinitionRegistry
@Override
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) {
int registryId = System.identityHashCode(registry);
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);
}
继续跟踪,会在processConfigBeanDefinitions
方法里看到以下的if else
第一个if就是检查是不是已经处理过了,从日志也能看出来,具体是获取一个属性:CONFIGURATION_CLASS_ATTRIBUTE,这个属性就是后面用来决定是Full模式还是Lite模式
public void processConfigBeanDefinitions(BeanDefinitionRegistry registry) {
List<BeanDefinitionHolder> configCandidates = new ArrayList<>();
String[] candidateNames = registry.getBeanDefinitionNames();
for (String beanName : candidateNames) {
BeanDefinition beanDef = registry.getBeanDefinition(beanName);
if (beanDef.getAttribute(ConfigurationClassUtils.CONFIGURATION_CLASS_ATTRIBUTE) != null) {
if (logger.isDebugEnabled()) {
logger.debug("Bean definition has already been processed as a configuration class: " + beanDef);
}
}
else if (ConfigurationClassUtils.checkConfigurationClassCandidate(beanDef, this.metadataReaderFactory)) {
configCandidates.add(new BeanDefinitionHolder(beanDef, beanName));
}
}
// ...
}
这里先说明一下,如果我们自己写了@Configuration
的类,实际上是在ConfigurationClassParser#doProcessConfigurationClass
方法中处理的,这个方法中也会调用ConfigurationClassUtils#checkConfigurationClassCandidate
,逻辑是一样的,上面可以当作是引出ConfigurationClassUtils#checkConfigurationClassCandidate
这个方法,暂且按照这个思路接着往下进行
下面主要看else逻辑,继续跟踪ConfigurationClassUtils#checkConfigurationClassCandidate
方法
这里面会设置刚才if中判断的那个属性:CONFIGURATION_CLASS_ATTRIBUTE
第一个if中获取@Configuration
的proxyBeanMethods
属性,如果不为false,就设置属性为:CONFIGURATION_CLASS_FULL
,这就是Full模式的条件
public static boolean checkConfigurationClassCandidate(
BeanDefinition beanDef, MetadataReaderFactory metadataReaderFactory) {
// ...
Map<String, Object> config = metadata.getAnnotationAttributes(Configuration.class.getName());
if (config != null && !Boolean.FALSE.equals(config.get("proxyBeanMethods"))) {
beanDef.setAttribute(CONFIGURATION_CLASS_ATTRIBUTE, CONFIGURATION_CLASS_FULL);
}
else if (config != null || isConfigurationCandidate(metadata)) {
beanDef.setAttribute(CONFIGURATION_CLASS_ATTRIBUTE, CONFIGURATION_CLASS_LITE);
}
else {
return false;
}
// ...
return true;
}
对应的,else if中就是Lite模式的条件
如果config==null,再看isConfigurationCandidate
方法,但是如果是标注@Configuration
的类,这里config一定不为null,暂且忽略isConfigurationCandidate
这个方法
也就是说,当proxyBeanMethods值为false,设置为Lite模式
到此,postProcessBeanDefinitionRegistry
这个方法调用中,关于Full模式和Lite模式的设置,就完成了,就是向BeanDefinition中设置一个属性CONFIGURATION_CLASS_ATTRIBUTE
,值为full或lite
abstract class ConfigurationClassUtils {
public static final String CONFIGURATION_CLASS_FULL = "full";
public static final String CONFIGURATION_CLASS_LITE = "lite";
// ...
}
下面看ConfigurationClassPostProcessor
中第二个调用的方法:postProcessBeanFactory
看一下这个方法注释,大概意思就是通过cglib增强
/**
* Prepare the Configuration classes for servicing bean requests at runtime
* by replacing them with CGLIB-enhanced subclasses.
*/
@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));
}
enhanceConfigurationClasses
这个方法中会判断之前设置的CONFIGURATION_CLASS_ATTRIBUTE属性,如果为full,就进行动态代理
public void enhanceConfigurationClasses(ConfigurableListableBeanFactory beanFactory) {
// ...
for (String beanName : beanFactory.getBeanDefinitionNames()) {
// ...
Object configClassAttr = beanDef.getAttribute(ConfigurationClassUtils.CONFIGURATION_CLASS_ATTRIBUTE);
// ...
if (ConfigurationClassUtils.CONFIGURATION_CLASS_FULL.equals(configClassAttr)) {
// ...
configBeanDefs.put(beanName, (AbstractBeanDefinition) beanDef);
}
}
// ...
ConfigurationClassEnhancer enhancer = new ConfigurationClassEnhancer();
for (Map.Entry<String, AbstractBeanDefinition> entry : configBeanDefs.entrySet()) {
// ...
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);
}
}
// ...
}
enhance
方法
public Class<?> enhance(Class<?> configClass, @Nullable ClassLoader classLoader) {
// ...
Class<?> enhancedClass = createClass(newEnhancer(configClass, classLoader));
// ...
return enhancedClass;
}
newEnhancer
方法
private Enhancer newEnhancer(Class<?> configSuperClass, @Nullable ClassLoader classLoader) {
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(configSuperClass);
enhancer.setInterfaces(new Class<?>[] {EnhancedConfiguration.class});
enhancer.setUseFactory(false);
enhancer.setNamingPolicy(SpringNamingPolicy.INSTANCE);
enhancer.setStrategy(new BeanFactoryAwareGeneratorStrategy(classLoader));
enhancer.setCallbackFilter(CALLBACK_FILTER);
enhancer.setCallbackTypes(CALLBACK_FILTER.getCallbackTypes());
return enhancer;
}
setCallbackFilter
中定义方法增强
private static final Callback[] CALLBACKS = new Callback[] {
new BeanMethodInterceptor(),
new BeanFactoryAwareMethodInterceptor(),
NoOp.INSTANCE
};
和@Bean
相关的处理是BeanMethodInterceptor
这就是cglib内容了,可以在方法中看到invokeSuper
调用
关于增强了啥,暂时不做讨论了
private static class BeanMethodInterceptor implements MethodInterceptor, ConditionalCallback {
@Override
@Nullable
public Object intercept(Object enhancedConfigInstance, Method beanMethod, Object[] beanMethodArgs,
MethodProxy cglibMethodProxy) throws Throwable {
// ...
return cglibMethodProxy.invokeSuper(enhancedConfigInstance, beanMethodArgs);
// ...
}
}