@ComponentScan 注解

在配置类上添加 @ComponentScan 注解。该注解默认会扫描该类所在的包下所有的配置类,相当于xml的 <context:component-scan>。

@ComponentScan注解默认就会装配标识了@Controller,@Service,@Repository,@Component注解的类到spring容器中。

新建三个类 

@Controller
public class OrderController {
}
@Service
public class OrderService {
}
@Repository
public class OrderDao {

}

配置类 

@Configuration
@ComponentScan("cn.qin.test")  //扫描该路径下的
public class Config {
}

查看容器中的Bean

    AnnotationConfigApplicationContext app=new AnnotationConfigApplicationContext(Config.Class);
        String[] names=app.getBeanDefinitionNames();
        for (String name : names){
            System.out.println(name);
        }



org.springframework.context.annotation.internalConfigurationAnnotationProcessor
org.springframework.context.annotation.internalAutowiredAnnotationProcessor
org.springframework.context.annotation.internalRequiredAnnotationProcessor
org.springframework.context.annotation.internalCommonAnnotationProcessor
org.springframework.context.event.internalEventListenerProcessor
org.springframework.context.event.internalEventListenerFactory
Config
orderController
orderDao
orderService


源码分析

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@Documented
@Repeatable(ComponentScans.class)
public @interface ComponentScan {
    /**
     * 对应的包扫描路径 可以是单个路径,也可以是扫描的路径数组
     * @return
     */
    @AliasFor("basePackages")
    String[] value() default {};
    /**
     * 和value一样是对应的包扫描路径 可以是单个路径,也可以是扫描的路径数组
     * @return
     */
    @AliasFor("value")
    String[] basePackages() default {};
    /**
     * 指定具体的扫描的类
     * @return
     */
    Class<?>[] basePackageClasses() default {};
    /**
     * 对应的bean名称的生成器 默认的是BeanNameGenerator
     * @return
     */
    Class<? extends BeanNameGenerator> nameGenerator() default BeanNameGenerator.class;
    /**
     * 处理检测到的bean的scope范围
     */
    Class<? extends ScopeMetadataResolver> scopeResolver() default AnnotationScopeMetadataResolver.class;
    /**
     * 是否为检测到的组件生成代理
     * Indicates whether proxies should be generated for detected components, which may be
     * necessary when using scopes in a proxy-style fashion.
     * <p>The default is defer to the default behavior of the component scanner used to
     * execute the actual scan.
     * <p>Note that setting this attribute overrides any value set for {@link #scopeResolver}.
     * @see ClassPathBeanDefinitionScanner#setScopedProxyMode(ScopedProxyMode)
     */
    ScopedProxyMode scopedProxy() default ScopedProxyMode.DEFAULT;
    /**
     * 控制符合组件检测条件的类文件   默认是包扫描下的  **/*.class
     * @return
     */
    String resourcePattern() default ClassPathScanningCandidateComponentProvider.DEFAULT_RESOURCE_PATTERN;
    /**
     * 是否对带有@Component @Repository @Service @Controller注解的类开启检测,默认是开启的
     * @return
     */
    boolean useDefaultFilters() default true;
    /**
     * 指定某些定义Filter满足条件的组件 FilterType有5种类型如:
     *                                  ANNOTATION, 注解类型 默认
                                        ASSIGNABLE_TYPE,指定固定类
                                        ASPECTJ, ASPECTJ类型
                                        REGEX,正则表达式
                                        CUSTOM,自定义类型
     * @return
     */
    Filter[] includeFilters() default {};
    /**
     * 排除某些过来器扫描到的类
     * @return
     */
    Filter[] excludeFilters() default {};
    /**
     * 扫描到的类是都开启懒加载 ,默认是不开启的
     * @return
     */
    boolean lazyInit() default false;
}

 

includeFilters 包含 
excludeFilters 排除
@Configuration
@ComponentScan(value = "cn.qin.test",includeFilters = {
        @ComponentScan.Filter(type = FilterType.ANNOTATION,classes = {Controller.class}),   // 注解类型  Controller
        @ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE,classes = {OrderService.class}),  //固定类型 是OrderService
},useDefaultFilters
= false) public class Config { }
一定要设置useDefaultFilters =false 不然无效
 
自定义 Filter
public class CustomFilter implements TypeFilter {
    /**
     *
     * @param metadataReader  读取当前正在扫描类的信息
     * @param metadataReaderFactory  可以获取到其他任何类的信息
     * @return
     * @throws IOException
     */
    public boolean match(MetadataReader metadataReader, MetadataReaderFactory metadataReaderFactory) throws IOException {
        //获取当前类的注解信息
        AnnotatedTypeMetadata annotatedTypeMetadata=metadataReader.getAnnotationMetadata();
        //获取正在扫描类的信息
        ClassMetadata classMetadata=metadataReader.getClassMetadata();
        //获取当前类资源(类的路径)
        Resource resource = metadataReader.getResource();

        String className=classMetadata.getClassName();
        System.out.println("正在扫描的类:"+className);

        if(className.contains("Controller")) //类名包含了Controller的才被放到容器中
        {
            return true;
        }

        return false;

    }
}
 

  

 



posted @ 2019-10-12 14:13  MartinEDM  阅读(406)  评论(0)    收藏  举报