最近做项目发现Spring核心配置文件中的<context:component-scan/>与<context:annotation-config/>配置经常一起出现,但有时候又单独出现,而且没有出现问题。今天抽空看了看源码,发现原来这俩个标签的处理逻辑及其相似(在处理我们经常使用的几个注解上基本如出一辙)。
起初,添加<context:annotation-config/>标签,想必是为了我们大家使用像@Autowired、@Resource、@PostConstruct、@PreDestroy等等标签方便,以为之前我们注册BeanPostProcessor都是直接在Spring配置文件中使用<bean/>标签声明的方式,如果使用的注解一旦多起来,像我这样的懒人实在是难以接受。像我们常用的几个:
@Autowired
<bean class="org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor "/>
@Resource/@PostConstruct/@PreDestroy
<bean class="org.springframework.context.annotation.CommonAnnotationBeanPostProcessor"/>
@Required
<bean class="org.springframework.beans.factory.annotation.RequiredAnnotationBeanPostProcessor"/>
@PersistenceContext
<bean class="org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor"/>
而<context:annotation-config/>的出现解放了我们的体力,只需一行配置就搞定了。
上源码:
<context:annotation-config/>由AnnotationConfigBeanDefinitionParser解析:
public class AnnotationConfigBeanDefinitionParser implements BeanDefinitionParser {
public BeanDefinition parse(Element element, ParserContext parserContext) {
Object source = parserContext.extractSource(element);
// Obtain bean definitions for all relevant BeanPostProcessors.
Set<BeanDefinitionHolder> processorDefinitions =
AnnotationConfigUtils.registerAnnotationConfigProcessors(parserContext.getRegistry(), source);//此处为BeanPostProcessor 注册部分
// Register component for the surrounding <context:annotation-config> element.
CompositeComponentDefinition compDefinition = new CompositeComponentDefinition(element.getTagName(), source);
parserContext.pushContainingComponent(compDefinition);
// Nest the concrete beans in the surrounding component.
for (BeanDefinitionHolder processorDefinition : processorDefinitions) {
parserContext.registerComponent(new BeanComponentDefinition(processorDefinition));
}
// Finally register the composite component.
parserContext.popAndRegisterContainingComponent();
return null;
}
}
AnnotationConfigUtils.registerAnnotationConfigProcessor(..)
public static Set<BeanDefinitionHolder> registerAnnotationConfigProcessors(
BeanDefinitionRegistry registry, Object source) {
Set<BeanDefinitionHolder> beanDefs = new LinkedHashSet<BeanDefinitionHolder>(4);
if (!registry.containsBeanDefinition(CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME)) {
RootBeanDefinition def = new RootBeanDefinition(ConfigurationClassPostProcessor.class);
def.setSource(source);
beanDefs.add(registerPostProcessor(registry, def, CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME));
}
if (!registry.containsBeanDefinition(AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME)) {
//@Autowired等
RootBeanDefinition def = new RootBeanDefinition(AutowiredAnnotationBeanPostProcessor.class);
def.setSource(source);
beanDefs.add(registerPostProcessor(registry, def, AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME));
}
if (!registry.containsBeanDefinition(REQUIRED_ANNOTATION_PROCESSOR_BEAN_NAME)) { //@Required等
RootBeanDefinition def = new RootBeanDefinition(RequiredAnnotationBeanPostProcessor.class);
def.setSource(source);
beanDefs.add(registerPostProcessor(registry, def, REQUIRED_ANNOTATION_PROCESSOR_BEAN_NAME));
}
// Check for JSR-250 support, and if present add the CommonAnnotationBeanPostProcessor.
if (jsr250Present && !registry.containsBeanDefinition(COMMON_ANNOTATION_PROCESSOR_BEAN_NAME)) { //@PostConstruct、@PreDestroy、@Resource等
RootBeanDefinition def = new RootBeanDefinition(CommonAnnotationBeanPostProcessor.class);
def.setSource(source);
beanDefs.add(registerPostProcessor(registry, def, COMMON_ANNOTATION_PROCESSOR_BEAN_NAME));
}
// Check for JPA support, and if present add the PersistenceAnnotationBeanPostProcessor.
if (jpaPresent && !registry.containsBeanDefinition(PERSISTENCE_ANNOTATION_PROCESSOR_BEAN_NAME)) { //@PersistenceContext
RootBeanDefinition def = new RootBeanDefinition();
try {
ClassLoader cl = AnnotationConfigUtils.class.getClassLoader();
def.setBeanClass(cl.loadClass(PERSISTENCE_ANNOTATION_PROCESSOR_CLASS_NAME));
}
catch (ClassNotFoundException ex) {
throw new IllegalStateException(
"Cannot load optional framework class: " + PERSISTENCE_ANNOTATION_PROCESSOR_CLASS_NAME, ex);
}
def.setSource(source);
beanDefs.add(registerPostProcessor(registry, def, PERSISTENCE_ANNOTATION_PROCESSOR_BEAN_NAME));
}
return beanDefs;
}
以上我们可以清晰的看到标签<context:annotation-config/>的解析过程以及注解相关的BeanPostProcessor的注册过程。接下来我们来看看<context:component-scan/>的逻辑:
ComponentScanBeanDefinitionParser
public class ComponentScanBeanDefinitionParser implements BeanDefinitionParser {
public BeanDefinition parse(Element element, ParserContext parserContext) {
String[] basePackages = StringUtils.tokenizeToStringArray(element.getAttribute(BASE_PACKAGE_ATTRIBUTE),
ConfigurableApplicationContext.CONFIG_LOCATION_DELIMITERS);
// Actually scan for bean definitions and register them.
ClassPathBeanDefinitionScanner scanner = configureScanner(parserContext, element); //扫描指定路径下的类,并注册BeanPostProcessor
Set<BeanDefinitionHolder> beanDefinitions = scanner.doScan(basePackages);
registerComponents(parserContext.getReaderContext(), beanDefinitions, element);
return null;
}
}
protected void registerComponents(
XmlReaderContext readerContext, Set<BeanDefinitionHolder> beanDefinitions, Element element) {
... ...
// Register annotation config processors, if necessary.
boolean annotationConfig = true;
if (element.hasAttribute(ANNOTATION_CONFIG_ATTRIBUTE)) {
annotationConfig = Boolean.valueOf(element.getAttribute(ANNOTATION_CONFIG_ATTRIBUTE));
}
if (annotationConfig) {
Set<BeanDefinitionHolder> processorDefinitions =
AnnotationConfigUtils.registerAnnotationConfigProcessors(readerContext.getRegistry(), source);
for (BeanDefinitionHolder processorDefinition : processorDefinitions) {
compositeDef.addNestedComponent(new BeanComponentDefinition(processorDefinition));
}
}
... ...
}
我们可以发现Spring默认<context:component-scan/>的annotation-config的属性值为true,当其为true时,才对一些BeanPostProcessor进行注册,也就是完成<context:annotation-config/>的任务。
从以上源码我们可以看出如果我们在使用<context:component-scan/>时不将其annotation-config属性设置为false的话,我们就可以不配置<context:annotation-config/>。