Spring 的 IOC 常用注解 (含源码)
一、容器中注入组件
1,包扫描 + 组件标注注解
源码:Demo01_ComponentScan
a)组件标注
@Controller
@Service
@Repository
@Component
b)包扫描 @ComponentScan
@ComponentScan 中主要值得解释
value:扫描的包路径(数组)
excludeFilters:指定扫描的时候按照什么规则排除那些组件(@ComponentScan.Filter)includeFilters:指定扫描的时候只需要包含哪些组件。使用同 excludeFilter。FilterType.ANNOTATION:按照注解 FilterType.ASSIGNABLE_TYPE:按照给定的类型 FilterType.ASPECTJ:使用 ASPECTJ 表达式 FilterType.REGEX:使用正则指定 FilterType.CUSTOM:使用自定义规则
useDefaultFilters:是否使用默认的扫描机制。默认按照 a)中组件标注扫描
2,使用 @Bean 导入
a)@Scope 作用域
prototype:多实例的:ioc 容器启动并不会去调用方法创建对象放在容器中。每次获取的时候才会调用方法创建对象;
singleton:单实例的(默认值):ioc 容器启动会调用方法创建对象放到 ioc 容器中。以后每次获取就是直接从容器(map.get())中拿,
request:同一次请求创建一个实例
session:同一个 session 创建一个实例
b)@Lazy
单实例 bean:默认在容器启动的时候创建对象;
懒加载:容器启动不创建对象。第一次使用(获取)Bean 创建对象,并初始化。
c)@Conditional
@Bean 上加改注解,按照一定的条件进行判断,满足条件给容器中注册 bean;如在类上加改注解,这个类中配置的所有 bean 注册才能生效。
@ConditionalOnClass 表示如果有后面的类,那么就加载这个自动配置;
@ConditionalOnMissingClass 如果没有后面的类,才自动配置。如果没有就配置,保证 bean 的唯一。
大量运用于 SpringBoot 中。
3,使用 @Import 导入
源码:Demo02_Import
快速为容器中导入一个组件。
@Import(要导入到容器中的组件);容器中就会自动注册这个组件,id 默认是全类名
ImportSelector:返回需要导入的组件的全类名数组
ImportBeanDefinitionRegistrar:手动注册 bean 到容器中
4,FactoryBean(工厂 Bean)
源码:Demo03_FactoryBean
将实现 FactoryBean 的类加到容器中。
默认从容器中获取到的是工厂 bean 调用 getObject 创建的对象。
要获取工厂 Bean 本身,我们需要给 id 前面加一个 &
二、Bean 的生命周期
1,bean 生命周期
bean 创建 --- 初始化 --- 销毁
构造(对象创建)单实例:在容器启动的时候创建对象多实例:在每次获取的时候创建对象
初始化:成员变量赋值,各种增强等,对象创建完成,并赋值好,调用初始化方法
销毁:单实例:容器关闭的时候多实例:容器不会管理这个 bean;容器不会调用销毁方法;
2,定义 Bean 初始化和销毁
a)定义 initMethod 和 destroyMethod
源码:Demo04_BeanLifeCycle、Car
定义初始化方法,定义 @Bean 的 initMethod 为该方法
定义销毁方法,定义 @Bean 的 destroyMethod 为该方法
b)实现 InitializingBean 和 DisposableBean 接口
源码:Demo04_BeanLifeCycle、Dog
定义当前对象实现 InitializingBean 接口。其中 afterPropertiesSet 方法会在当前对象设置完属性之后调用。
定义当前对象实现 DisposableBean 接口。其中 destroy 方法会在当前对象销毁的时候调用。
c)可以使用 JSR250
源码:Demo04_BeanLifeCycle、Color
@PostConstruct 定义在方法上,则该方法会在 Bean 创建并且属性赋值之后执行,为初始化方法
@PreDestroy 定义在方法上,则该方法在容器销毁 bean 之前通知我们进行清理工作
d)实现 BeanPostProcessor,bean 的后置处理
源码:Demo04_BeanLifeCycle、Demo04_BeanPostProccessor
在 bean 初始化前后进行一些处理工作;
postProcessBeforeInitialization:在初始化之前工作
postProcessAfterInitialization:在初始化之后工作
3,从源码看 BeanPostProcessor 后置处理器
在 Spring 类 AbstractAutowireCapableBeanFactory 中方法 doCreateBean 可以看到
在方法 initializeBean 中可以看到
总结:
BeanPostProcessor 会在 Bean 对象创建并属性赋值完成之后,在执行 init 初始化方法的前后进行增加。
4,BeanPostProcessor 在 Spring 中的应用
a)ApplicationContextAware 各种 Aware 接口
查看源码类 ApplicationContextAwareProcessor 实现了 BeanPostProcessor 接口,其中 postProcessBeforeInitialization 的实现为:
所以在 ApplicationContextAware 时,可以通过 setApplicationContext 获取到 ApplicationContext 上下文对象
b)BeanValidationPostProcessor
查看 BeanValidationPostProcessor 实现了 BeanPostProcessor 接口,其中不管是 postProcessBeforeInitialization 还是 postProcessAfterInitialization,均调用了 doValidate 方法来验证当前 bean 是否合理
c)@PostConstruct 和 @PreDestroy 方法
查看 InitDestroyAnnotationBeanPostProcessor 实现了 BeanPostProcessor 接口,其中 postProcessBeforeInitialization 在当前 bean 初始化之前的源码为:
d)AutowiredAnnotationBeanPostProcessor
用来处理 @Autowire 注解的属性
三、属性赋值
@Value:给属性赋值,也可以使用 SpEL 和外部文件的值
@PropertySource:读取外部配置文件中的 k/v 保存到运行环境中。@PropertySource(value={"classpath:/application.yaml"})
@Autowried 装配优先级如下:构造器、参数、方法、属性。
使用按照类型去容器中找对应的组件
如果找到多个相同类型的组件,再将属性的名称作为组件的 id 去容器中查找
@Qualifier:使用 @Qualifier 指定需要装配的组件的 id,结合 @Autowried 使用
@Primary:spring 自动装配的时候,默认首先 bean,配合 @Bean 使用
@Resource(JSR250):jsr 规范:按照组件名称进行装配,不支持 @Primary 和 @Autowired(reqiured=false)
@Inject(JSR330):jsr 规范和 @Autowired 功能一致,不支持 require=false;
@Profile:结合 @Bean 使用,默认为 default 环境,可以通过命令行参数来切换环境加上 VM 参数:-Dspring.profiles.active=dev 则采用了 dev 环境。多个用逗号隔开 1.无参构造 ApplicationContext,2.通过 applicationContext.getEnvironment().setActiveProfiles("dev"),3.注册配置类 applicationContext.register(Main.class),4.采用 ApplicationContext.refresh()
版权声明: 本文为 InfoQ 作者【Java王路飞】的原创文章。
原文链接:【http://xie.infoq.cn/article/cc38ae217db4b1a161ec26648】。未经作者许可,禁止转载。
评论