注解自动扫描原理分析
在spring的配置文件中加入如下代码,spring便开启了自动扫描,那么它的底层到底是如何实现的呢?
<context:component-scan base-package="com.wisely.highlight_spring4.ch1"/>
-
首先找到解析这个标签的地方,spring 中解析具体的标签都有相应的解析器,且都继承了NamespaceHandlerSupport
-
查看
ComponentScanBeanDefinitionParser
的parse
方法
-
真正的逻辑其实是在
ClassPathBeanDefinitionScanner
的doScan
方法中
-
测试一下扫描过程

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 }
-
我的项目包结构
-
控制台输出结果