我是靠谱客的博主 淡定发夹,最近开发中收集的这篇文章主要介绍为什么说Spring框架只会将标注有@Component、@Named、@ManagedBean注解的类加入到容器? @Configuration、@Controller又为什么会加入到容器中?,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

Spring只会把标注有@Component、@Named、@ManagedBean注解的类加入到容器内,但是我们使用@Controller、@Service、@Repository注解也能加入到容器,这是怎么实现的?

Spring注解配置启动的整个过程是这样的,首先Spring遍历所有文件夹获取到类文件,将类文件封装成Resource,使用MetadataReader对Resource进行读取,读取到类的注解等信息,然后再根据注解进行筛选,符合条件的封装成BeanDefinition。有了BeanDefinition就可以生成Bean了。在这个过程中负责扫描的是ClassPathScanningCandidateComponentProvider类,来看一下这个类的实现

public class ClassPathScanningCandidateComponentProvider2 implements EnvironmentCapable, ResourceLoaderAware {

	//...
	private final List<TypeFilter> includeFilters = new LinkedList<>();
	//...

	//在类实例化是调用了这个方法,注册了@Component、@Named、@ManagedBean三个注解
	protected void registerDefaultFilters() {
		//注册@Component
		this.includeFilters.add(new AnnotationTypeFilter(Component.class));
		ClassLoader cl = ClassPathScanningCandidateComponentProvider2.class.getClassLoader();
		try {
			//注册@ManagedBean
			this.includeFilters.add(new AnnotationTypeFilter(
					((Class<? extends Annotation>) ClassUtils.forName("javax.annotation.ManagedBean", cl)), false));
			logger.trace("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 {
			//注册@Named
			this.includeFilters.add(new AnnotationTypeFilter(
					((Class<? extends Annotation>) ClassUtils.forName("javax.inject.Named", cl)), false));
			logger.trace("JSR-330 'javax.inject.Named' annotation found and supported for component scanning");
		}
		catch (ClassNotFoundException ex) {
			// JSR-330 API not available - simply skip.
		}
	}
	//...
	
	//这个是扫描的方法,这里对类上的注解进行了过滤,只保留了标有@Component、@Named、@ManagedBean的类,并封装成BeanDefinition
	private Set<BeanDefinition> scanCandidateComponents(String basePackage) {
		Set<BeanDefinition> candidates = new LinkedHashSet<>();
		//...
		//使用资源加载器,获取所有类文件,并分装成Resource
		Resource[] resources = getResourcePatternResolver().getResources(packageSearchPath);
		//...
		for (Resource resource : resources) {
			//...
			//读取类的信息
			MetadataReader metadataReader = getMetadataReaderFactory().getMetadataReader(resource);
			//这个判断是关键,只有标注有@Component、@ManagedBean、@Named注解的才会是true,走下面流程生成BeanDefinition
			if (isCandidateComponent(metadataReader)) {
				//生成Beand定义
				ScannedGenericBeanDefinition sbd = new ScannedGenericBeanDefinition(metadataReader);
				sbd.setSource(resource);
				//...
				//添加到结果集中
				candidates.add(sbd);
			}
			//...
		}
		return candidates;
	}
	//...

	protected boolean isCandidateComponent(MetadataReader metadataReader) throws IOException {
		//...
		//这里遍历includeFilters,在类registerDefaultFilters方法执行后,向includeFilters添加了@Component、@Named、@ManagedBean类型过滤器
		for (TypeFilter tf : this.includeFilters) {
			//判断类是否标注有tf类型的注解
			if (tf.match(metadataReader, getMetadataReaderFactory())) {
				//Condition条件判断
				return isConditionMatch(metadataReader);
			}
		}
		return false;
	}
}

总结一下,首先在类实例化的时候调用了registerDefaultFilters方法注册了@Component、@Named、@ManagedBean类型的过滤器。在扫描完成后调用isCandidateComponent方法逐个判断,符合条的才会生成BeanDefinition。isCandidateComponent方法内遍历注册的过滤器与类进行匹配,符合的再进行Condition判断成功的返回true。

看完上面代码好像Spring只能识别三个注解,那@Controller、@Service、@Repository又是怎么识别的呢?请看下篇

最后

以上就是淡定发夹为你收集整理的为什么说Spring框架只会将标注有@Component、@Named、@ManagedBean注解的类加入到容器? @Configuration、@Controller又为什么会加入到容器中?的全部内容,希望文章能够帮你解决为什么说Spring框架只会将标注有@Component、@Named、@ManagedBean注解的类加入到容器? @Configuration、@Controller又为什么会加入到容器中?所遇到的程序开发问题。

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

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

评论列表共有 0 条评论

立即
投稿
返回
顶部