在配置类上添加 @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; } }