spring context:component-scan与context:annotation-config的区别

前言

< context:annotation-config/>

用来注册几个常用的BeanPostProcessor,常见的BeanPostProcessor有ConfigurationClassPostProcessorAutowiredAnnotationBeanPostProcessorCommonAnnotationBeanPostProcessor,他们主要用来解析@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_NAMEAUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME 等几个常量,在此列了一个表

常量对应的BeanPostProcessor对应的注解
CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAMEConfigurationClassPostProcessor@Configuration
AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAMEAutowiredAnnotationBeanPostProcessor@AutoWired、@Value、@javax.inject.Inject
REQUIRED_ANNOTATION_PROCESSOR_BEAN_NAMERequiredAnnotationBeanPostProcessor@Required
COMMON_ANNOTATION_PROCESSOR_BEAN_NAMECommonAnnotationBeanPostProcessor@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下的类。

  • 综上所述,两者只能留其一。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值