spring注解开发:ComponentScan组件扫描
在使用xml方式配置时,我们只需要在xml中配置如下代码:
<context:component-scan base-package="包名"></context:component-scan>
那么在java代码中使用如下四个注解,并且这些注解所在的包名是上面配置的包及其子包,那么spring会帮我们把相应的bean加如到IOC容器中。
- @Controller
- @Service
- @Repository
- @Component
在注解的方式下如何实现呢?在我们的配置类的上面加上如下注解即可
@ComponentScan(value={"包名1","包名2"})
此时该注解指定的几个包名及其子包中如果有类被上面四个注解修饰,那么就会自动被注入到IOC容器中。
注意:如果ComponentScan没有其它配置的化,默认扫描与其配置类相同的包。
1、实战
新建一个maven工程,添加如下依赖
<dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>5.0.5.RELEASE</version> </dependency>
1、BookController
package com.yefengyu.annotation.controller; import org.springframework.stereotype.Controller; @Controller public class BookController { }
2、BookService
package com.yefengyu.annotation.service; import org.springframework.stereotype.Service; @Service public class BookService { }
3、BookRepository
package com.yefengyu.annotation.repository; import org.springframework.stereotype.Repository; @Repository public class BookRepository { }
4、主配置类
package com.yefengyu.annotation.config; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; @Configuration @ComponentScan(value = "com.yefengyu.annotation") public class MainConfig { }
5、测试
public static void main(String[] args) { ApplicationContext ctx= new AnnotationConfigApplicationContext(MainConfig.class); String[] names = ctx.getBeanDefinitionNames(); for (String name : names) { System.out.println(name); } }
6、结果
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
mainConfig
bookController
bookRepository
bookService
结果打印出如上内容,说明上面三个注解的bean都被添加到容器中。
2、规则过滤
@ComponentScan除了value 属性之外,还有其他属性,其中比较常用的是如下两个:
- excludeFilters :排除哪些规则
- includeFilters :指定哪些规则
他们的作用就是指定过滤规则。
1、指定规则
对于上面的代码,只需要修改主配置类中ComponentScan注解中的内容即可:
@ComponentScan(value = "com.yefengyu.annotation", includeFilters = {@ComponentScan.Filter(type = FilterType.ANNOTATION, classes = Service.class)},useDefaultFilters = false)
上面的注解的含义是在com.yefengyu.annotation及其子包下面,将注解为Service的bean加入到容器中。注意useDefaultFilters 默认为true,表示使用默认的过滤规则:不过滤;如果需要指定规则,那么就需要将useDefaultFilters 设置为false。注意includeFilters 和useDefaultFilters 同时使用即可。
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
mainConfig
bookService
2、排除规则
对于上面的代码,只需要修改主配置类中ComponentScan注解中的内容即可:
@ComponentScan(value = "com.yefengyu.annotation", excludeFilters = {@ComponentScan.Filter(type = FilterType.ANNOTATION, classes = Service.class)})
如果要排除某些规则,就要使用excludeFilters ,注意不需要使用useDefaultFilters ,默认即可。
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
mainConfig
bookController
bookRepository
上面注解的含义就是在com.yefengyu.annotation及其子包下面,将注解为Controller的bean排除容器之外。
3、FilterType的类型
- ANNOTATION:注解,常用
- ASSIGNABLE_TYPE:给定类型,该类型及其子类、接口的实现类都起作用
- ASPECTJ
- REGEX:正则
- CUSTOM:自定义
自定义类型的使用方式:
package com.yefengyu.annotation; import org.springframework.core.io.Resource; import org.springframework.core.type.AnnotationMetadata; import org.springframework.core.type.ClassMetadata; import org.springframework.core.type.classreading.MetadataReader; import org.springframework.core.type.classreading.MetadataReaderFactory; import org.springframework.core.type.filter.TypeFilter; import java.io.IOException; public class MyTypeFilter implements TypeFilter { @Override public boolean match(MetadataReader metadataReader, MetadataReaderFactory metadataReaderFactory) throws IOException { //获取当前类注解信息 AnnotationMetadata annotationMetadata = metadataReader.getAnnotationMetadata(); //获取当前扫描的类的信息 ClassMetadata classMetadata = metadataReader.getClassMetadata(); //获取当前扫描类资源信息 Resource resource = metadataReader.getResource(); String className = classMetadata.getClassName(); if (className.contains("er")) { return true; } return false; } }
实现TypeFilter接口,重写match方法,满足条件的则返回true.
然后指定扫描策略:
@ComponentScan(value = "com.yefengyu.annotation", excludeFilters = {@ComponentScan.Filter(type = FilterType.CUSTOM, classes = MyTypeFilter.class)})
结果如下:
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
mainConfig
bookRepository
将类中含有er的排除在外。
4、指定多个ComponentScan
1、在jdk8以后可以直接写多个ComponentScan
@ComponentScan(basePackages = "com.yefengyu.annotation1")
@ComponentScan(basePackages = "com.yefengyu.annotation2")
2、也可以使用ComponentScans注解
@ComponentScans(value = { @ComponentScan(basePackages = "com.yefengyu.annotation1"), @ComponentScan(basePackages = "com.yefengyu.annotation2") })