我是靠谱客的博主 哭泣长颈鹿,最近开发中收集的这篇文章主要介绍annotation-config 与 component-scan 标签,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

annotation-config

标签解析入口

org.springframework.context.annotation.AnnotationConfigBeanDefinitionParser

我们只看核心部分

		// Obtain bean definitions for all relevant BeanPostProcessors.
		Set<BeanDefinitionHolder> processorDefinitions =
				AnnotationConfigUtils.registerAnnotationConfigProcessors(parserContext.getRegistry(), source);

这个方法里会注入一系列的后置处理器

ConfigurationClassPostProcessor处理 @Configuration 标签表注的类
AutowiredAnnotationBeanPostProcessor处理 @Autowired 标签
RequiredAnnotationBeanPostProcessor处理 @Required 标签
CommonAnnotationBeanPostProcessor处理 @Resource、@WebServiceRef、@EJB
PersistenceAnnotationBeanPostProcessor处理 @PersistenceUnit @PersistenceContext

 

 

component-scan

 

标签解析入口

org.springframework.context.annotation.ComponentScanBeanDefinitionParser

主方法很简洁,如下

	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);
		Set<BeanDefinitionHolder> beanDefinitions = scanner.doScan(basePackages);
		registerComponents(parserContext.getReaderContext(), beanDefinitions, element);

		return null;
	}

 

1、获得需要扫描的路径集合,这个是根据base-package配置来计算出来的

2、实例化一个扫描器,这里返回的实例是:ClassPathBeanDefinitionScanner 对象

3、扫描获得bean定义

4、向容器中注册这些bean定义

我们看看ClassPathBeanDefinitionScanner的创建过程:

protected ClassPathBeanDefinitionScanner createScanner(XmlReaderContext readerContext, boolean useDefaultFilters) {
		return new ClassPathBeanDefinitionScanner(readerContext.getRegistry(), useDefaultFilters);
	}

再看看父类(ClassPathScanningCandidateComponentProvider)构造方法里做了什么

protected void registerDefaultFilters() {
		this.includeFilters.add(new AnnotationTypeFilter(Component.class));
		ClassLoader cl = ClassPathScanningCandidateComponentProvider.class.getClassLoader();
		try {
			this.includeFilters.add(new AnnotationTypeFilter(
					((Class<? extends Annotation>) ClassUtils.forName("javax.annotation.ManagedBean", cl)), false));
			logger.debug("JSR-250 'javax.annotation.ManagedBean' found and supported for component scanning");
		}
		catch (ClassNotFoundException ex) {
			// JSR-250 1.1 API (as included in Java EE 6) not available - simply skip.
		}
		try {
			this.includeFilters.add(new AnnotationTypeFilter(
					((Class<? extends Annotation>) ClassUtils.forName("javax.inject.Named", cl)), false));
			logger.debug("JSR-330 'javax.inject.Named' annotation found and supported for component scanning");
		}
		catch (ClassNotFoundException ex) {
			// JSR-330 API not available - simply skip.
		}
	}

这里向 includeFilters 里添加了一个 TypeFilter

this.includeFilters.add(new AnnotationTypeFilter(Component.class));

也就是说这个扫描器会默认扫描带有Component注解的类或者带有Component的组合注解类(例如:@Repository,@Controller @Service,@Configuration等)

两者关系

我们来到注册组件的方法

org.springframework.context.annotation.ComponentScanBeanDefinitionParser#registerComponents

这个方法主要作用是将扫描到的bean定义注册到容器中,另一个重要作用是引入annotation-config操作相关的后置处理器

protected void 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));
		}
//这里是两者关系的关键代码,与annotation-config标签做了相同的事情
		if (annotationConfig) {
			Set<BeanDefinitionHolder> processorDefinitions =
					AnnotationConfigUtils.registerAnnotationConfigProcessors(readerContext.getRegistry(), source);
			for (BeanDefinitionHolder processorDefinition : processorDefinitions) {
				compositeDef.addNestedComponent(new BeanComponentDefinition(processorDefinition));
			}
		}

		readerContext.fireComponentRegistered(compositeDef);
	}

也就是说component-scan 首先会扫描到自己需要管理的Component组件,再向容器中注入annotation-config相关的后置处理器;这也就是两者之间的关系了。

 

最后

以上就是哭泣长颈鹿为你收集整理的annotation-config 与 component-scan 标签的全部内容,希望文章能够帮你解决annotation-config 与 component-scan 标签所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(47)

评论列表共有 0 条评论

立即
投稿
返回
顶部