类路径Bean定义扫描器ClassPathBeanDefinitionScanner主要通过findCandidateComponents方法调用其父类ClassPathScanningCandidateComponentProvider类来扫描获取给定包及其子包下的类。
(3).ClassPathScanningCandidateComponentProvider扫描给定包及其子包的类:
ClassPathScanningCandidateComponentProvider类的findCandidateComponents方法具体实现扫描给定类路径包的功能,主要源码如下:
[java] view plaincopy- public class ClassPathScanningCandidateComponentProvider implements ResourceLoaderAware { //保存过滤规则要包含的注解,即Spring默认的@Component、@Repository、@Service、//@Controller注解的Bean,以及JavaEE6的@ManagedBean和JSR-330的@Named注解
- private final List
includeFilters = new LinkedList (); //保存过滤规则要排除的注解 - private final List
excludeFilters = new LinkedList (); //构造方法,该方法在子类ClassPathBeanDefinitionScanner的构造方法中被调用 - public ClassPathScanningCandidateComponentProvider(boolean useDefaultFilters) { //如果使用Spring默认的过滤规则,则向容器注册过滤规则
- if (useDefaultFilters) { registerDefaultFilters();
- } }
- //向容器注册过滤规则 protected void registerDefaultFilters() {
- //向要包含的过滤规则中添加@Component注解类,注意Spring中@Repository //@Service和@Controller都是Component,因为这些注解都添加了@Component注解
- this.includeFilters.add(new AnnotationTypeFilter(Component.class)); //获取当前类的类加载器
- ClassLoader cl = ClassPathScanningCandidateComponentProvider.class.getClassLoader(); try {
- //向要包含的过滤规则添加JavaEE6的@ManagedBean注解 this.includeFilters.add(new AnnotationTypeFilter(
- ((Class ) cl.loadClass(javax.annotation.ManagedBean)), false)); logger.info(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 ) cl.loadClass(javax.inject.Named)), false));
- logger.info(JSR-330 'javax.inject.Named' annotation found and supported for component scanning); }
- catch (ClassNotFoundException ex) { // JSR-330 API not available - simply skip.
- } }
- //扫描给定类路径的包 public Set
findCandidateComponents(String basePackage) { - //创建存储扫描到的类的集合 Set
candidates = new LinkedHashSet (); - try { //解析给定的包路径,this.resourcePattern=” **/*.class”,
- //ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX=“classpath:” //resolveBasePackage方法将包名中的”.”转换为文件系统的”/”
- String packageSearchPath = ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX + resolveBasePackage(basePackage) + / + this.resourcePattern;
- //将给定的包路径解析为Spring资源对象 Resource[] resources = this.resourcePatternResolver.getResources(packageSearchPath);
- boolean traceEnabled = logger.isTraceEnabled(); boolean debugEnabled = logger.isDebugEnabled();
- //遍历扫描到的资源 for (Resource resource : resources) {
- if (traceEnabled) { logger.trace(Scanning + resource);
- } if (resource.isReadable()) {
- try { //为指定资源获取元数据读取器,元信息读取器通过汇编(ASM)读//取资源元信息
- MetadataReader metadataReader = this.metadataReaderFactory.getMetadataReader(resource); //如果扫描到的类符合容器配置的过滤规则
- if (isCandidateComponent(metadataReader)) { //通过汇编(ASM)读取资源字节码中的Bean定义元信息
- ScannedGenericBeanDefinition sbd = n