首页 > 技术文章 > Spring-扫描注解原理,注解自动扫描原理分析

hoonick 2018-10-19 17:32 原文

 

注解自动扫描原理分析

 

在spring的配置文件中加入如下代码,spring便开启了自动扫描,那么它的底层到底是如何实现的呢?

<context:component-scan base-package="com.wisely.highlight_spring4.ch1"/>

 

  1. 首先找到解析这个标签的地方,spring 中解析具体的标签都有相应的解析器,且都继承了NamespaceHandlerSupport
    在这里插入图片描述
    在这里插入图片描述

  2. 查看 ComponentScanBeanDefinitionParserparse方法
    在这里插入图片描述

  3. 真正的逻辑其实是在ClassPathBeanDefinitionScannerdoScan方法中
    在这里插入图片描述

  4. 测试一下扫描过程

 1 package com.wisely.highlight_spring4.ch1.di;
 2 
 3 import java.io.IOException;
 4 import java.util.LinkedHashSet;
 5 import java.util.Set;
 6 
 7 import org.springframework.beans.factory.config.BeanDefinition;
 8 import org.springframework.context.annotation.ScannedGenericBeanDefinition;
 9 import org.springframework.core.io.Resource;
10 import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
11 import org.springframework.core.io.support.ResourcePatternResolver;
12 import org.springframework.core.type.classreading.MetadataReader;
13 import org.springframework.core.type.classreading.MetadataReaderFactory;
14 import org.springframework.core.type.classreading.SimpleMetadataReaderFactory;
15 import org.springframework.stereotype.Component;
16 import org.springframework.stereotype.Controller;
17 import org.springframework.stereotype.Service;
18 
19 public class BeanFactoryTest
20 {
21     public static void main(String[] args) throws IOException, ClassNotFoundException {
22         Set<BeanDefinition> candidates = new LinkedHashSet<>();
23 
24         ResourcePatternResolver resourcePatternResolver = new PathMatchingResourcePatternResolver();  
25         //这里特别注意一下类路径必须这样写
26         //获取指定包下的所有类
27         Resource[] resources = resourcePatternResolver.getResources("classpath*:com\\wisely\\highlight_spring4\\ch1\\di\\*");  
28          
29         MetadataReaderFactory metadata=new SimpleMetadataReaderFactory();
30         for(Resource resource:resources) {
31             System.out.println(resource);
32             MetadataReader metadataReader=metadata.getMetadataReader(resource);
33             ScannedGenericBeanDefinition sbd = new ScannedGenericBeanDefinition(metadataReader);
34             sbd.setResource(resource);
35             sbd.setSource(resource);
36             candidates.add(sbd);
37         }
38         for(BeanDefinition beanDefinition : candidates) {  
39             String classname=beanDefinition.getBeanClassName();
40             //扫描controller注解
41             Controller c=Class.forName(classname).getAnnotation(Controller.class);
42             //扫描Service注解
43             Service s=Class.forName(classname).getAnnotation(Service.class);
44             //扫描Component注解
45             Component component=Class.forName(classname).getAnnotation(Component.class);
46             if(c!=null ||s!=null ||component!=null){       
47                 System.out.println(classname);
48             }
49         } 
50     }
51 }
View Code

 

  1. 我的项目包结构
    在这里插入图片描述

  2. 控制台输出结果
    在这里插入图片描述

 

推荐阅读