传送:
Spring大观园,我有过的困惑或许你也有!
导读
spring内部对配置类分为两种,区分的办法是:
解析后,在beanDef中添加属性"configurationClass",其值分两种,要么是"full" ,要么是"lite";
1. beanDef.setAttribute(CONFIGURATION_CLASS_ATTRIBUTE, CONFIGURATION_CLASS_FULL);
2. beanDef.setAttribute(CONFIGURATION_CLASS_ATTRIBUTE, CONFIGURATION_CLASS_LITE);
替换常量后是这样
1. beanDef.setAttribute("configurationClass"), "full");
2. beanDef.setAttribute("configurationClass"), "lite");
有何区别:
- full类的是带有
@Configuration
注解的配置类 - lite类的是
2.1 类上带有注解@Component
、@ComponentScan
、@Import
、@Component
、@ImportResource
;
2.2 类中的方法带有注解@Bean
避免重复解析
因为解析后,会在beanDef中setAttribute("configurationClass"), "full"/"lite");
所以,如果beanDef.getAttribute("configurationClass")不是null 就是被解析过了
if (beanDef.getAttribute(ConfigurationClassUtils.CONFIGURATION_CLASS_ATTRIBUTE) != null) {
if (logger.isDebugEnabled()) {
logger.debug("Bean definition has already been processed as a configuration class: " + beanDef);
}
}
源码视角
注解方式的配置类 的解析操作从
ConfigurationClassPostProcessor#processConfigBeanDefinitions
方法中查看,
其中有个判断配置类的方法有点特别
ConfigurationClassUtils.checkConfigurationClassCandidate
...
Map config = metadata.getAnnotationAttributes(Configuration.class.getName());
if (config != null && !Boolean.FALSE.equals(config.get("proxyBeanMethods"))) {
//如果有有注解@Configuration,且其元数据中有"proxyBeanMethods",则为 full
beanDef.setAttribute(CONFIGURATION_CLASS_ATTRIBUTE, CONFIGURATION_CLASS_FULL);
}
else if (config != null || isConfigurationCandidate(metadata)) {
// lite 自己跟踪其源码一看便知
beanDef.setAttribute(CONFIGURATION_CLASS_ATTRIBUTE, CONFIGURATION_CLASS_LITE);
}
else {
return false;
}
...
了解配置类
如果是配置类,spring会对其进行解析,导入、扫描BeanDefinition,配置类解析从两个视角来:
- 脑图全晰视角:配置类解析流程
- 源码注释版的链接稍后敬上。