前言:
通过上一个demo,应该能初步体会到spring 基于注解的开发流程。那下面介绍几个新的与组件注入相关的注解:@ComponentScans/@ComponentScan/@Controller/@Service/@Repository/@Component
准备工作:
新建 controller、service、dao三个package,并在其中分别定义三个类:如 UserController、UserService、UserDao(三各类当然在三个不同的package下,类中可以暂时什么也不定义)。
实验:
除了通过@Bean之外,还可以通过下面这样的方式将其分别注入到IOC容器中:
- 首先,分别在 UserController、UserService、UserDao 这三个类上标注上 @Controller、@Service、@Repository 注解(这一点学过spring的应该都不陌生)。
@Controller
public class UserController {
}
@Service
public class UserService {
}
@Repository
public class UserDao {
}
- 其次,在SpringConfig1配置类上使用 @ConfigurationScan 注解。该注解最简单的用法就是通过 bacePackages 属性指定扫描哪些包及其子包下面的类,将其注入到IOC容器。例如
@Configuration
@ComponentScan(basePackages="com.uestc.auto.xiaoxie")
public class SpringConfig1 {
@Bean
public Person person(){
return new Person("kristina", 24);
}
}
- 编写测试方法,看新定义的三个类有没有注入到容器中。
// 包扫描
@Test
public void testComponentScan() {
// 获取ioc容器中所有bean的name
String[] names = context.getBeanDefinitionNames();
for (String name : names) {
System.out.println(name);
}
}
- 该注解还有一些很常用的属性。我们可以点进去查看详细信息:首先可以看到这是一个“可重复”注解 ~ @Repeatable 注解,即我们可以使用多个 @ComponentScan 定义不同的扫描规则,或者使用 @ComponentScans 包含多个 @ComponentScan。
- includeFilters:指定在进行包扫描的时候,按照什么规则包含哪些包;但是 includeFilters 需要结合 useDefaultFilters=false 一起使用,否则默认扫描全部;
- excludeFilters:指定在进行包扫描的时候,按照什么规则排除哪些包。
- 按住 Ctrl 键,点击 includeFilters 或者 excludeFilters 前面的 Filter,可以看到这又是一个注解(@Filter):
@Filter 注解的 type 属性用于指定包扫描规则,type 属性的取值为一个枚举类 FilterType。且通过 type 属性上面的注释,我们可以进一步明确:
type属性的取值 | 对应的含义 |
---|---|
FilterType.ANNOTATION | 默认取值 ,按照指定的注解扫描/排除包 |
FilterType.ASSIGNABLE_TYPE | 按照指定的类型扫描/排除包 |
FilterType.ASPECTJ | 还可以写 aspectj 表达式 |
FilterType.REGEX | 还可以写正则表达式 |
FilterType.CUSTOM | 还可以自定义包扫描规则 |
- 示例代码:
@Configuration
@ComponentScans(value={
@ComponentScan(basePackages="com.uestc.auto.xiaoxie", useDefaultFilters=false, includeFilters={
@Filter(type=FilterType.ANNOTATION, classes={Controller.class, Service.class}),
@Filter(type=FilterType.ASSIGNABLE_TYPE, classes={UserDao.class}),
@Filter(type=FilterType.CUSTOM, classes={MyTypeFilter.class})})
})
public class SpringConfig1 {
@Bean(value="person")
public Person person01(){
return new Person("kristina", 24);
}
}
注意,扫描规则的最后一行 @Filter(type=FilterType.CUSTOM, classes={MyTypeFilter.class}) 为自定义的。
从上图中可以看出,自定义包扫描需要实现 TypeFilter 接口。如下所示:
/*
* 自定义包扫描规则
*/
public class MyTypeFilter implements TypeFilter {
/*
* @param metadataReader:当前类的信息
* @param metadataReaderFactory:可以从中获取到其它任何类的信息
* @return true:扫描当前类
* false:过滤当前类
* @throws IOException
*/
@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.equals("userDao")){
return true;
}
return false;
}
}
- 任意组合包扫描规则,再次调用第三步的测试方法,体会有哪些变化。