最近做项目发现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/>。