Spring @ComponentScan注解 —— 自动扫描组件

@ComponentScan主要就是定义扫描的路径从中找出标识了需要装配的类自动装配到spring的bean容器中.

@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE})
@Documented
//可以多个ComponentScans注解
@Repeatable(ComponentScans.class)
public @interface ComponentScan {
    //basePackages与value:用于指定包的路径,进行扫描,默认值为当前类所在包
    @AliasFor("basePackages")
    String[] value() default {};
 
    @AliasFor("value")
    String[] basePackages() default {};
 
    //用于指定某个类的包的路径进行扫描
    Class[] basePackageClasses() default {};
    
    //bean的名称的生成器
    Class nameGenerator() default BeanNameGenerator.class;
 
    //处理检测到的bean的scope范围
    Class scopeResolver() default AnnotationScopeMetadataResolver.class;
 
    //是否为检测到的组件生成代理,动态代理使用,默认为 不
    ScopedProxyMode scopedProxy() default ScopedProxyMode.DEFAULT;
 
    //控制符合组件检测条件的类文件  默认是包扫描下的  **/*.class,
    String resourcePattern() default ClassPathScanningCandidateComponentProvider.DEFAULT_RESOURCE_PATTERN;
    //是否开启对@Component,@Repository,@Service,@Controller的类进行检测,相当于默认的includeFilters
    boolean useDefaultFilters() default true;
    
    //包含的过滤条件 FilterType.ANNOTATION:按照注解过滤,FilterType.ASSIGNABLE_TYPE:按照给定的类型,FilterType.ASPECTJ:使用ASPECTJ表达式,FilterType.REGEX:正则,FilterType.CUSTOM:自定义规则
    ComponentScan.Filter[] includeFilters() default {};
    
    //排除的过滤条件,用法和includeFilters一样
    ComponentScan.Filter[] excludeFilters() default {};
    
    //扫描到的类是都开启懒加载 ,默认是不开启的
    boolean lazyInit() default false;
    

    @Retention(RetentionPolicy.RUNTIME)
    @Target({})
    public @interface Filter {
        FilterType type() default FilterType.ANNOTATION;
        @AliasFor("classes")
        Class[] value() default {};
        @AliasFor("value")
        Class[] classes() default {};
        String[] pattern() default {};
    }
}

basePackages的使用

ApplicationContext applicationContext = new AnnotationConfigApplicationContext(ScanConfig.class);
String[] beanDefinitionNames = applicationContext.getBeanDefinitionNames();
for (String beanName : beanDefinitionNames) {
      System.out.println("beanName: " + beanName);
}


//默认值为当前所在包ComponentScan(ScanConfig.class)
//也可以写@ComponentScan("com.moyao")
@ComponentScan
public class ScanConfig {
}

@Controller
public class UserController {
}


结果:
beanName: org.springframework.context.annotation.internalConfigurationAnnotationProcessor
beanName: org.springframework.context.annotation.internalAutowiredAnnotationProcessor
beanName: org.springframework.context.annotation.internalRequiredAnnotationProcessor
beanName: org.springframework.context.annotation.internalCommonAnnotationProcessor
beanName: org.springframework.context.event.internalEventListenerProcessor
beanName: org.springframework.context.event.internalEventListenerFactory
beanName: scanConfig
beanName: userController

excludeFilters的使用


//把扫到,注释中有Controller的过滤了
@ComponentScan(
        excludeFilters = {@ComponentScan.Filter(type = FilterType.ANNOTATION,
                value = {Controller.class})})
public class ScanConfig {
}

结果:
beanName: org.springframework.context.annotation.internalConfigurationAnnotationProcessor
beanName: org.springframework.context.annotation.internalAutowiredAnnotationProcessor
beanName: org.springframework.context.annotation.internalRequiredAnnotationProcessor
beanName: org.springframework.context.annotation.internalCommonAnnotationProcessor
beanName: org.springframework.context.event.internalEventListenerProcessor
beanName: org.springframework.context.event.internalEventListenerFactory
beanName: scanConfig

includeFilters的使用

@ComponentScan(useDefaultFilters = false,
        includeFilters  = {@ComponentScan.Filter(type = FilterType.ANNOTATION,
                value = {Controller.class})})
public class ScanConfig {
}

结果:
beanName: org.springframework.context.annotation.internalConfigurationAnnotationProcessor
beanName: org.springframework.context.annotation.internalAutowiredAnnotationProcessor
beanName: org.springframework.context.annotation.internalRequiredAnnotationProcessor
beanName: org.springframework.context.annotation.internalCommonAnnotationProcessor
beanName: org.springframework.context.event.internalEventListenerProcessor
beanName: org.springframework.context.event.internalEventListenerFactory
beanName: scanConfig
beanName: userController
  • @ComponentScan 中将 useDefaultFilters 设为 false ,ComponentScan不会扫描入包下的Controller,这时include的才起作用。
  • 另外可能自定义添加过Filter

源码分析

从《spring容器扩展分析》得知,对注解的处理都发生在AbstractApplicationContext -> refresh() -> invokeBeanFactoryPostProcessors(beanFactory) -> ConfigurationClassPostProcessor -> postProcessBeanDefinitionRegistry()-->ConfigurationClassParser->parser->doProcessConfigurationClass方法中。

// Process any @ComponentScan annotations
Set<AnnotationAttributes> componentScans = AnnotationConfigUtils.attributesForRepeatable(
      sourceClass.getMetadata(), ComponentScans.class, ComponentScan.class);
if (!componentScans.isEmpty() &&
      !this.conditionEvaluator.shouldSkip(sourceClass.getMetadata(), ConfigurationPhase.REGISTER_BEAN)) {
   for (AnnotationAttributes componentScan : componentScans) {
       //马上执行扫描
       //获取扫描路径下的定义的Bean的BeanDefinition信息
      Set<BeanDefinitionHolder> scannedBeanDefinitions =
            this.componentScanParser.parse(componentScan, sourceClass.getMetadata().getClassName());
      // Check the set of scanned definitions for any further config classes and parse recursively if needed
      for (BeanDefinitionHolder holder : scannedBeanDefinitions) {
         BeanDefinition bdCand = holder.getBeanDefinition().getOriginatingBeanDefinition();
         if (bdCand == null) {
            bdCand = holder.getBeanDefinition();
         }
         if (ConfigurationClassUtils.checkConfigurationClassCandidate(bdCand, this.metadataReaderFactory)) {
            parse(bdCand.getBeanClassName(), holder.getBeanName());
         }
      }
   }
}


//对有ComponentScan的进行解析
//主要向scanner设置ComponentScan提供的参数
public Set<BeanDefinitionHolder> parse(AnnotationAttributes componentScan, final String declaringClass) {
  //使用默认过滤器
  //如果useDefaultFilters为true,则会this.includeFilters.add(new AnnotationTypeFilter(Component.class));
ClassPathBeanDefinitionScanner scanner = new ClassPathBeanDefinitionScanner(this.registry,
       componentScan.getBoolean("useDefaultFilters"), this.environment, this.resourceLoader);

//被扫入的类名字生成器
 Class<? extends BeanNameGenerator> generatorClass = componentScan.getClass("nameGenerator");
 boolean useInheritedGenerator = (BeanNameGenerator.class == generatorClass);
 scanner.setBeanNameGenerator(useInheritedGenerator ? this.beanNameGenerator :
       BeanUtils.instantiateClass(generatorClass));


 ScopedProxyMode scopedProxyMode = componentScan.getEnum("scopedProxy");
 if (scopedProxyMode != ScopedProxyMode.DEFAULT) {
    scanner.setScopedProxyMode(scopedProxyMode);
 }
 else {
    Class<? extends ScopeMetadataResolver> resolverClass = componentScan.getClass("scopeResolver");
    scanner.setScopeMetadataResolver(BeanUtils.instantiateClass(resolverClass));
 }

 scanner.setResourcePattern(componentScan.getString("resourcePattern"));

 for (AnnotationAttributes filter : componentScan.getAnnotationArray("includeFilters")) {
    for (TypeFilter typeFilter : typeFiltersFor(filter)) {
       scanner.addIncludeFilter(typeFilter);
    }
 }
 for (AnnotationAttributes filter : componentScan.getAnnotationArray("excludeFilters")) {
    for (TypeFilter typeFilter : typeFiltersFor(filter)) {
       scanner.addExcludeFilter(typeFilter);
    }
 }

 boolean lazyInit = componentScan.getBoolean("lazyInit");
 if (lazyInit) {
    scanner.getBeanDefinitionDefaults().setLazyInit(true);
 }

 Set<String> basePackages = new LinkedHashSet<>();
  //获取扫描路径
 String[] basePackagesArray = componentScan.getStringArray("basePackages");
 for (String pkg : basePackagesArray) {
    String[] tokenized = StringUtils.tokenizeToStringArray(this.environment.resolvePlaceholders(pkg),
          ConfigurableApplicationContext.CONFIG_LOCATION_DELIMITERS);
    Collections.addAll(basePackages, tokenized);
 }
  //获取扫描类
 for (Class<?> clazz : componentScan.getClassArray("basePackageClasses")) {
    basePackages.add(ClassUtils.getPackageName(clazz));
 }
 if (basePackages.isEmpty()) {
    basePackages.add(ClassUtils.getPackageName(declaringClass));
 }

 scanner.addExcludeFilter(new AbstractTypeHierarchyTraversingFilter(false, false) {
    @Override
    protected boolean matchClassName(String className) {
       return declaringClass.equals(className);
    }
 });
 return scanner.doScan(StringUtils.toStringArray(basePackages));
}

以上对参数进行整合,全部汇入Scanner中
protected Set<BeanDefinitionHolder> doScan(String... basePackages) {
        Assert.notEmpty(basePackages, "At least one base package must be specified");
        Set<BeanDefinitionHolder> beanDefinitions = new LinkedHashSet<>();
        for (String basePackage : basePackages) {
            //根据路径进行扫描组件
            Set<BeanDefinition> candidates = findCandidateComponents(basePackage);
            for (BeanDefinition candidate : candidates) {
                ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(candidate);
                candidate.setScope(scopeMetadata.getScopeName());
               //name生成类生成组件名
                String beanName = this.beanNameGenerator.generateBeanName(candidate, this.registry);
                if (candidate instanceof AbstractBeanDefinition) {
                    postProcessBeanDefinition((AbstractBeanDefinition) candidate, beanName);
                }
                if (candidate instanceof AnnotatedBeanDefinition) {
                    AnnotationConfigUtils.processCommonDefinitionAnnotations((AnnotatedBeanDefinition) candidate);
                }
                if (checkCandidate(beanName, candidate)) {
                    //是否lazy设置到对象中 
                    BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(candidate, beanName);
                    definitionHolder =
//是否生成代理的调用类                            AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
                    beanDefinitions.add(definitionHolder);
                    //对返回的BeanDefinition注册到BeanFactory,后续统一实例化。
                    registerBeanDefinition(definitionHolder, this.registry);
                }
            }
        }
        return beanDefinitions;
    }


private Set<BeanDefinition> scanCandidateComponents(String basePackage) {
 Set<BeanDefinition> candidates = new LinkedHashSet<>();
 try {
     //拼接读取.class文件的资源路径,例如classpath*:garine/learn/test/**/*.class
     //对注释中的this.resourcePattern进行使用
    String packageSearchPath = ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX +
          resolveBasePackage(basePackage) + '/' + this.resourcePattern;
     //读取路径下的所有.class文件信息
    Resource[] resources = getResourcePatternResolver().getResources(packageSearchPath);
    boolean traceEnabled = logger.isTraceEnabled();
    boolean debugEnabled = logger.isDebugEnabled();
    for (Resource resource : resources) {
       if (traceEnabled) {
          logger.trace("Scanning " + resource);
       }
       if (resource.isReadable()) {
          try {
              //org.springframework.core.type.classreading.CachingMetadataReaderFactory#getMetadataReader
//获取.class对应的元信息,例如注解信息等
             MetadataReader metadataReader = getMetadataReaderFactory().getMetadataReader(resource);
              //根据注解元信息判断是不是符合条件的.class
             if (isCandidateComponent(metadataReader)) {
                ScannedGenericBeanDefinition sbd = new ScannedGenericBeanDefinition(metadataReader);
                sbd.setResource(resource);
                sbd.setSource(resource);
                 //判断能否实例化
                if (isCandidateComponent(sbd)) {
                    //添加到候选BeanDefinition
                   candidates.add(sbd);
                }
                else {
                   //忽略
                }
             }
             else {
                if (traceEnabled) {
                   logger.trace("Ignored because not matching any filter: " + resource);
                }
             }
          }
          catch (Throwable ex) {
             throw new BeanDefinitionStoreException(
                   "Failed to read candidate component class: " + resource, ex);
          }
       }
       else {
          if (traceEnabled) {
             logger.trace("Ignored because not readable: " + resource);
          }
       }
    }
 }
 catch (IOException ex) {
    throw new BeanDefinitionStoreException("I/O failure during classpath scanning", ex);
 }
 return candidates;
}

//对过滤器Filter的使用
protected boolean isCandidateComponent(MetadataReader metadataReader) throws IOException {
		for (TypeFilter tf : this.excludeFilters) {
			if (tf.match(metadataReader, this.metadataReaderFactory)) {
				return false;
			}
		}
		for (TypeFilter tf : this.includeFilters) {
			if (tf.match(metadataReader, this.metadataReaderFactory)) {
				return isConditionMatch(metadataReader);
			}
		}
		return false;
	}

//找到的bean是否用代理
static BeanDefinitionHolder applyScopedProxyMode(
			ScopeMetadata metadata, BeanDefinitionHolder definition, BeanDefinitionRegistry registry) {

		ScopedProxyMode scopedProxyMode = metadata.getScopedProxyMode();
		if (scopedProxyMode.equals(ScopedProxyMode.NO)) {
			return definition;
		}
		boolean proxyTargetClass = scopedProxyMode.equals(ScopedProxyMode.TARGET_CLASS);
		return ScopedProxyCreator.createScopedProxy(definition, registry, proxyTargetClass);
	}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值