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

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

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

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
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注解的类加入到容器?内容请搜索靠谱客的其他文章。

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

评论列表共有 0 条评论

立即
投稿
返回
顶部