为什么要使用注解编程
注解编程可以使得代码更简洁,提供开发效率。
替换xml这种配置形式,简化配置
例如 开发一个User类:
1 | public class User(){....} |
添加注解@Component后如下:
1 |
|
该形式等价于在spring配置文件中的
1 | <bean id="user" class="com.study.User"></bean> |
容器相关注解
组件注册
@Configuration
作用在类上,表示这个是一个配置类,相当于配置文件xml一样
@Bean
作用在方法上,和 bean 标签功能一致,返回值是class,方法名默认是id,也可以指定
@ComponentScan
作用在类上,配置扫描包,可以使用excludeFilters或includeFilters来过滤或指定包含哪个类
使用excludeFilters:过滤掉哪些类
1 |
|
使用includeFilters:包含哪些类
1 |
|
@ComponentScans
配置扫描包,可以设置多个值
1 |
自动过滤规则:
1 | public class MyTypeFilter implements TypeFilter{ |
1 |
@Scope
作用在方法上,相当于 bean 中的scope属性
1 | /** |
@Lazy
懒加载,作用单实例bean中,原来的单实例bean在spring容器加载后会自动创建实例,加了此注解后,会在第一次使用到此bean时才会创建。
1 |
|
@Conditional
可以作用在类或方法上。
作用在方法上: 如果条件返回true,则创建bean
作用在类上: 如果返回true,此类的注册bean才会生效。
1 |
|
1 | //判断是否是Linux系统 |
1 |
|
@Import
作用:快速的给容器导入一个组件
使用方法1:
1
2,容器中就会自动注册这个组件,id是类的全路径
使用方法2:
ImportSelector:返回需要导入的组件的全类名数组,这个在springboot中底层很常用1
2
3
4
5
6
7
8
9
10//实现ImportSelector接口
public class MyImportSelector implements ImportSelector{
//importingClassMetadata:注解信息
public String[] selectImports(AnnotationMetadata importingClassMetadata) {
return new String[]{"com.oyr.bean.Red", "com.oyr.bean.Yellow"};
}
}使用方法3:
ImportBeanDefinitionRegistrar:手动注册bean到容器中1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18//实现ImportBeanDefinitionRegistrar接口
public class MyImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar{
/**
* importingClassMetadata:注解信息
* registry:bean注册对象
*/
public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
//是否有id为red Bean
boolean b1 = registry.containsBeanDefinition("com.oyr.bean.Red");
//是否有id为yellow bean
boolean b2 = registry.containsBeanDefinition("com.oyr.bean.Yellow");
if(b1 && b2){
registry.registerBeanDefinition("blue", new RootBeanDefinition(Blue.class));
}
}
}
容器注册逐渐总结:
- 包扫描 + 逐渐标注注解(@Controller/ @Service/ @Repository/ @Componnet)
- Bean 导入的第三方包里面的组件
- import 快速的给融资导入一个组件
- @Import 需要导入容器中的bean,容器就会自动注解这个Bean,id是类的全路径
- ImportSelector: 返回需要导入的组件的全类名数组
- ImportBeanDefinitionRegistrar 手动注册bean到容器中
- 使用spring提供的FactoryBean(goncBean)
- 默认获取到的是工厂bean调用getObject()创建的对象
- 要获取到工厂bean本身,我们要在id前面加一个&
Bean 生命周期
指定初始化方法和销毁方法
- 对象的创建:
- 单实例: 在容器启动的时候创建对象
- 多实例: 在每次获取对象时创建
- 初始化:
- 对象创建完成,并赋值好,调用初始化方法
- 销毁:
- 单实例在容器关闭的时候销毁
- 多实例不会调用销毁方法,spring并不销毁,需要自己调用销毁方法。
使用@Bean指定初始化方法和销毁方法
1
2
3
4
public Color color(){
return new Color();
}通过让bena实现InitializingBean(定义初始化逻辑), DisposableBean(定义销毁逻辑)
1
2
3
4
5
6
7
8
9
10
11
12public class Color2 implements InitializingBean, DisposableBean{
public void destroy() throws Exception {
// TODO Auto-generated method stub
System.out.println("destroy");
}
public void afterPropertiesSet() throws Exception {
// TODO Auto-generated method stub
System.out.println("afterPropertiesSet");
}
}使用JSR250
@PostConstruct:在bean创建完成并且属性赋值完成:来执行初始化方法
@PreDestroy:在容器销毁bena之前通知我们进行销毁工作
BeanPostProcessor:bean的前后置处理器
在bean初始化前后进行一些处理工作
postProcessBeforeInitialization:在初始化之前工作
postProcessAfterInitialization:在初始化之后进行工作
spring底层对BeanPostProcessor的使用:
Bean赋值,注入其他组件,@AutoWitred,生命周期注解功能,@Async,等等
都是使用BeanPostProcessor实现的。