通过上一篇文章《Spring框架基本结构介绍》,已经对Spring的结构已经有了大概的了解
接下来学习Spring IOC 容器底层注解使用。
一、 Bean的定义方式
①XML配置文件的形式
1 | <?xml version="1.0" encoding="UTF-8"?> |
1 | public static void main( String[] args ) |
②Java配置类的形式
1. @Bean
1
2
3
4@Bean(initMethod = "init", destroyMethod = "destory") //指定这个Bean的创建方法以及销毁方法,方法写在Bean的实体里
public Tiger tiger() {
return new Tiger();
}
通过@Bean的形式是使用的话, bean的默认名称是方法名,若要指定Bean的名字需要通过@Bean(value=”bean的名称”)这种方式来指定。
1.1: initMethod 指定Bean的初始化方法
1.2: destroyMethod 指定Bean的销毁方法(多实例的Bean销毁由GC处理,不受容器控制)
注:Bean的其他几种初始化方法放在GitHub的代码中,本文不多做解释,链接在文末
2. @Scpoe
配置Bean的作用域对象,在不指定@Scope的情况下,所有的bean都是单实例的bean,而且是饿汉加载(容器启动实例就创建好了),指定@Scope为 prototype 表示为多实例、懒汉模式加载(IOC容器启动的时候,并不会创建对象,而是在第一次使用的时候才会创建)
@Scope指定作用域的几种方法:
a) singleton 单实例的(默认)
b) prototype 多实例的
c) request 同一次请求
d) session 同一个会话级别
1
2
3
4
5
6
7
8
9
10
11
12
13
14/**
* 指定@Scope为 prototype 表示为多实例的,而且还是懒汉式加载
* singleton 单实例的(默认)
* prototype 多实例的
* request 同一次请求
* session 同一个会话级别
*
* @return
*/
@Bean
@Scope(value = "prototype")
public Mouse mouse() {
return new Mouse();
}
3.@Lazy
懒加载(主要针对单实例的bean 容器启动的时候,不创建对象,在第一次使用的时候才会创建该对象)
1
2
3
4
5
6//使@Bean变成单例,懒汉式加载
@Bean
@Lazy
public Dog dog() {
return new Dog();
}
4.@Conditional
用于进行条件判断等,用法如下
1 | @Bean |
二、向IOC 容器中添加组件的方式
1.@CompentScan
在配置类上写@CompentScan注解来进行扫描指定包,包含(@Controller @Service@Respository @Compent)的组件,并添加到容器中。
1
2
3
4
5@Configuration
@ComponentScan(basePackages = {"org.smallmouse.scan"})
public class ScanConfig {
}1.1: 排除方法 excludeFilters
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15@Configuration
/**
* 注解形式的FilterType.ANNOTATION @Controller @Service @Repository @Compent
* 指定类型的 FilterType.ASSIGNABLE_TYPE
* aspectj类型的 FilterType.ASPECTJ(不常用)
* 正则表达式的 FilterType.REGEX(不常用)
* 自定义的 FilterType.CUSTOM
*/
@ComponentScan(basePackages = {"org.smallmouse.scan"},excludeFilters = {
@ComponentScan.Filter(type = FilterType.ANNOTATION,value = {Controller.class}),
@ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE,value = {DogDao.class})
})//扫描时过滤掉@Controller和DogDao类型
public class ScanConfig {
}
1.2: 包含方法 includeFilters (若使用包含的用法,需要把useDefaultFilters属性设置为false,true表示扫描全部)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15@Configuration
/**
* 注解形式的FilterType.ANNOTATION @Controller @Service @Repository @Compent
* 指定类型的 FilterType.ASSIGNABLE_TYPE
* aspectj类型的 FilterType.ASPECTJ(不常用)
* 正则表达式的 FilterType.REGEX(不常用)
* 自定义的 FilterType.CUSTOM
*/
@ComponentScan(basePackages = {"org.smallmouse.scan"},includeFilters = {
@ComponentScan.Filter(type = FilterType.ANNOTATION,value = {Repository.class}),
@ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE,value = {CatDao.class})
},useDefaultFilters = false)//引入@Repository和CatDao类型,引入时要将useDefaultFilters(默认为true,表示扫描全部)设置成false
public class ScanConfig {
}
1.3: @ComponentScan.Filter FilterType的类型
a)注解形式的FilterType.ANNOTATION ( @Controller @Service @Repository @Compent )
b)指定类型的 FilterType.ASSIGNABLE_TYPE @ComponentScan.Filter(type =FilterType.ASSIGNABLE_TYPE,value = {CatService.class})
c)aspectj类型的 FilterType.ASPECTJ(不常用,不做过多赘述)
d)正则表达式类型的 FilterType.REGEX(不常用,不做过多赘述)
e)自定义的 FilterType.CUSTOM1.4: FilterType.CUSTOM 使用方法
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20//自定义的FilterType需要实现TypeFilter接口
public class ZooFilterType implements TypeFilter {
@Override
public boolean match(MetadataReader metadataReader, MetadataReaderFactory metadataReaderFactory)
throws IOException {
//获取当前注解源信息
AnnotationMetadata annotationMetadata = metadataReader.getAnnotationMetadata();
//获取当前类class源信息
ClassMetadata classMetadata = metadataReader.getClassMetadata();
//获取当前类资源信息
Resource resource = metadataReader.getResource();
if (classMetadata.getClassName().contains("dao")) {
System.out.println("print true");
return true; //返回true的时候才会执行includeFilters或excludeFilters的逻辑
}
return false;//返回false的时候@ComponentScan只会扫描到自身
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16@Configuration
/**
* 注解形式的FilterType.ANNOTATION @Controller @Service @Repository @Compent
* 指定类型的 FilterType.ASSIGNABLE_TYPE
* aspectj类型的 FilterType.ASPECTJ(不常用)
* 正则表达式的 FilterType.REGEX(不常用)
* 自定义的 FilterType.CUSTOM
*/
@ComponentScan(basePackages = {"org.smallmouse.scan"},includeFilters = {
@ComponentScan.Filter(type = FilterType.ANNOTATION,value = {Repository.class}),
@ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE,value = {CatDao.class}),
@ComponentScan.Filter(type = FilterType.CUSTOM,value = {ZooFilterType.class})//设置自定义的FilterType类
},useDefaultFilters = false)//引入@Repository和CatDao类型,引入时要将useDefaultFilters(默认为true,表示扫描全部)设置成false
public class ScanConfig {
}
2.@Bean(这种方式在上面已经有讲过,此处就不多做赘述)
3.@Import (导入组件的id为全类名路径)
1 | @Configuration |
3.1: 通过@Import 的ImportSeletor类实现组件的导入 (导入组件的id为全类名路径)
1 | public class ZooImportSelector implements ImportSelector { |
3.2: 通过@Import的 ImportBeanDefinitionRegister导入组件(可以指定bean的名称)
1 | public class ZooBeanDefinitionRegister implements ImportBeanDefinitionRegistrar { |
4. 通过实现FacotryBean接口注册组件
1 | public class TigerFactoryBean implements FactoryBean<Tiger> { |
三、其他
1.@Profile
@Profile标识在类上,那么只有当前环境匹配,整个配置类才会生效
@Profile标识在Bean上 ,那么只有当前环境的Bean才会被激活
没有标志为@Profile的bean 不管在什么环境都可以被激活
2. @Configuration
标志着这个类是一个配置类
关于 @Controller @Service @Repository @Compent @Autowired等,开发中常用到的注解,想必大家对它们的使用已经早就已经熟练甚至精通了,这里就不多做赘述了。