前言
< context:annotation-config/>
用来注册几个常用的BeanPostProcessor,常见的BeanPostProcessor有ConfigurationClassPostProcessor
、AutowiredAnnotationBeanPostProcessor
、CommonAnnotationBeanPostProcessor
,他们主要用来解析@Autowired
、@required
、@Configuration
、@Component
,简单来说,BeanPostProcessor是让这些注解生效的。
<context:component-scan/>
包含了< context:annotation-config/> 的作用,同时还注册base-package下的注解类。
如果理解了上述所说,那么也就懂得,no bean named springsessionrepositoryfilter is defined
,就是因为没配置此两项之一。
解读源码
为了更好的理解这两个标签,有必要阅读源码。
< context:annotation-config/>源码
首先找到ContextNamespaceHandler
,它用来解析context命名空间下的元素,看一下继承层次图
public class ContextNamespaceHandler extends NamespaceHandlerSupport {
@Override
public void init() {
//只保留重要的两句
registerBeanDefinitionParser("annotation-config", new AnnotationConfigBeanDefinitionParser());
registerBeanDefinitionParser("component-scan", new ComponentScanBeanDefinitionParser());
}
}
annotation-config对应AnnotationConfigBeanDefinitionParser
,
主要看parse方法,
public class AnnotationConfigBeanDefinitionParser implements BeanDefinitionParser {
@Override
@Nullable
public BeanDefinition parse(Element element, ParserContext parserContext) {
Object source = parserContext.extractSource(element);
// 获取所有与BeanPostProcessors有关的bean定义.
Set<BeanDefinitionHolder> processorDefinitions =
AnnotationConfigUtils.registerAnnotationConfigProcessors(parserContext.getRegistry(), source);
return null;
}
}
在AnnotationConfigUtils.registerAnnotationConfigProcessors
中获取所有BeanPostProcessor
的bean
public static Set<BeanDefinitionHolder> registerAnnotationConfigProcessors(
BeanDefinitionRegistry registry, @Nullable Object source) {
DefaultListableBeanFactory beanFactory = unwrapDefaultListableBeanFactory(registry);
if (beanFactory != null) {
if (!(beanFactory.getDependencyComparator() instanceof AnnotationAwareOrderComparator)) {
beanFactory.setDependencyComparator(AnnotationAwareOrderComparator.INSTANCE);
}
if (!(beanFactory.getAutowireCandidateResolver() instanceof ContextAnnotationAutowireCandidateResolver)) {
beanFactory.setAutowireCandidateResolver(new ContextAnnotationAutowireCandidateResolver());
}
}
Set<BeanDefinitionHolder> beanDefs = new LinkedHashSet<>(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)) {
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)) {
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)) {
RootBeanDefinition def = new RootBeanDefinition(CommonAnnotationBeanPostProcessor.class);
def.setSource(source);
beanDefs.add(registerPostProcessor(registry, def, COMMON_ANNOTATION_PROCESSOR_BEAN_NAME));
}
//...
return beanDefs;
}
这里用到了CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME
、AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME
等几个常量,在此列了一个表
常量 | 对应的BeanPostProcessor | 对应的注解 |
---|---|---|
CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME | ConfigurationClassPostProcessor | @Configuration |
AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME | AutowiredAnnotationBeanPostProcessor | @AutoWired、@Value、@javax.inject.Inject |
REQUIRED_ANNOTATION_PROCESSOR_BEAN_NAME | RequiredAnnotationBeanPostProcessor | @Required |
COMMON_ANNOTATION_PROCESSOR_BEAN_NAME | CommonAnnotationBeanPostProcessor | @javax.annotation.PostConstruct、@javax.annotation.PreDestroy、@javax.annotation.Resource |
等等,还有几个,就不列了。
<context:component-scan/>源码
类似的,我们看ComponentScanBeanDefinitionParser
的parse方法
public BeanDefinition parse(Element element, ParserContext parserContext) {
String basePackage = element.getAttribute(BASE_PACKAGE_ATTRIBUTE);
basePackage = parserContext.getReaderContext().getEnvironment().resolvePlaceholders(basePackage);
String[] basePackages = StringUtils.tokenizeToStringArray(basePackage,
ConfigurableApplicationContext.CONFIG_LOCATION_DELIMITERS);
// Actually scan for bean definitions and register them.
ClassPathBeanDefinitionScanner scanner = configureScanner(parserContext, element);
Set<BeanDefinitionHolder> beanDefinitions = scanner.doScan(basePackages);
registerComponents(parserContext.getReaderContext(), beanDefinitions, element);
return null;
}
简单来说,就是扫描属性base-package
指定包下的类,然后注册,那重点就在registerComponents
方法了。
registerComponents(
XmlReaderContext readerContext, Set<BeanDefinitionHolder> beanDefinitions, Element element) {
Object source = readerContext.extractSource(element);
CompositeComponentDefinition compositeDef = new CompositeComponentDefinition(element.getTagName(), source);
for (BeanDefinitionHolder beanDefHolder : beanDefinitions) {
compositeDef.addNestedComponent(new BeanComponentDefinition(beanDefHolder));
}
// 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));
}
}
readerContext.fireComponentRegistered(compositeDef);
}
可以看出此方法就做了两件事,一是注册base-package下的类,二是调用AnnotationConfigUtils.registerAnnotationConfigProcessors
注册BeanPostProcessor,跟< context:annotation-config/>一模一样。到此就真相大白了。
总结
再来总结一遍,
-
< context:annotation-config/>注册了常用的
BeanPostProcessor
,而这些BeanPostProcessor
就是让常用注解(@AutoWired、@Configuration)生效。 -
<context:component-scan/> 做了< context:annotation-config/>所有做的事,除此之外,还扫描注册base-package下的类。
-
综上所述,两者只能留其一。