Spring学习笔记–高级特性之后置处理器
Spring提供了两种后处理bean的扩展接⼝,分别为 BeanPostProcessor 和BeanFactoryPostProcessor,两者在使⽤上是有所区别的。
工厂初始化(BeanFactory)—> Bean对象
在BeanFactory初始化之后可以使⽤BeanFactoryPostProcessor进⾏后置处理做⼀些事情
在Bean对象实例化(并不是Bean的整个⽣命周期完成)之后可以使⽤BeanPostProcessor进⾏后置处理做⼀些事情
注意:对象不⼀定是springbean,⽽springbean⼀定是个对象SpringBean的⽣命周期
SpringBean的生命周期
- 根据配置情况调用Bean构造方法或者工厂方法实例化Bean
- 利用依赖注入完成Bean中所有属性值的注入
- 如果Bean实现了BeanNameAware接口,则Spring调用Bean的setBeanName()方法传入当前Bean的id值。
- 如果Bean实现了BeanFactoryAware接口,则Spring调用setBeanFactory()传入当前工厂实例的引用。
- 如果Bean实现了ApplicationContextAware接口,则Spring调用setApplicationContext()方法传入当前ApplicationContext实例的引用。
- 如果BeanPostProcessor和Bean关联,则Spring将调用该接口的预初始化方法。postProcessBeforeInitialzation()对Bean进行加工操作,此处非常重要,Spring的AOP就是利用它来实现的。
- 如果Bean实现了InitializingBean接口,则Spring将调用afterPropertiesSet()方法。
- 如果在配置文件中通过init-method属性指定了初始化方法,则调用该初始化方法。
- 如果BeanPostProcessor和Bean关联,则Spring将调用该接口的初始化方法postProcessAfterInitialization()。此时Bean已经可以被应用系统使用了。
- 如果在中指定了该Bean的作用范围为scope=“singleton”,则将该Bean放入SpringIoc的缓存池中,将触发Spring对该Bean生命周期管理,如果在中指定了该Bean的作用范围scope=“prototype”,则将交给JVM对Bean的生命周期就行管理。
- 如果Bean实现了DisposableBean接口,则Spring会调用destory()方法将Spring中的Bean进行销毁,如果在配置文件中通过destory-method属性制定了Bean的销毁方法,则Spring将调用该方法对Bean进行销毁。
注意:Spring为Bean提供了细致全面的生命周期过程,通过实现特定的接口或者的属性设置,都可以对 Bean 的⽣命周期过程产⽣影响。虽然可以随意配置 的属性,但是建议不要过多地使⽤ Bean 实现接⼝,因为这样会导致代码和 Spring 的聚合过于紧密
在实例化Bean之前,需要先去将Bean解析成BeanDefinition
public class Result implements BeanNameAware,BeanFactoryAware,ApplicationContextAware,InitializingBean, DisposableBean {
private String status;
private String message;
public String getStatus() {
return status;
}
public void setStatus(String status) {
this.status = status;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
@Override
public String toString() {
return "Result{" +
"status='" + status + '\'' +
", message='" + message + '\'' +
'}';
}
@Override
public void setBeanName(String name) {
System.out.println("注册我成为bean时定义的id:" + name);
}
@Override
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
System.out.println("管理我的beanfactory为:" + beanFactory);
}
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
System.out.println("高级容器接口ApplicationContext:" + applicationContext);
}
@Override
public void afterPropertiesSet() throws Exception {
System.out.println("afterPropertiesSet......");
}
public void initMethod() {
System.out.println("init-method....");
}
@PostConstruct
public void postCoustrcut() {
System.out.println("postCoustrcut");
}
@PreDestroy
public void PreDestroy(){
System.out.println("PreDestroy...");
}
@Override
public void destroy() throws Exception {
System.out.println("destroy.....");
}
}
其中initMethod方法和@PostConstruct修饰的postConstruct方法都是在bean创建时
BeanPostProcessor
创建BeanPostProcessor实现类
拦截实例化之后的对象,实例化并且属性注入了。
@Component
public class MyBeanPostProcessor implements BeanPostProcessor {
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
if("lazyResult".equalsIgnoreCase(beanName)) {
System.out.println("MyBeanPostProcessor before方法拦截处理lazyResult");
}
return bean;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
if("lazyResult".equalsIgnoreCase(beanName)) {
System.out.println("MyBeanPostProcessor after方法拦截处理lazyResult");
}
return bean;
}
}
该接⼝提供了两个⽅法,分别在Bean的初始化⽅法前和初始化⽅法后执⾏,具体这个初始化⽅法指的是
什么⽅法,类似我们在定义bean时,定义了init-method所指定的⽅法定义⼀个类实现了BeanPostProcessor,默认是会对整个Spring容器中所有的bean进⾏处理。如果要对具体的某个bean处理,可以通过⽅法参数判断,两个类型参数分别为Object和String,第⼀个参数是每
个bean的实例,第⼆个参数是每个bean的name或者id属性的值。所以我们可以通过第⼆个参数,来判断我们将要处理的具体的bean。
BeanFactoryPostProcessor
BeanFactory级别的处理,是针对整个Bean的⼯⼚进⾏处理,典型应⽤:PropertyPlaceholderConfigurer
@FunctionalInterface
public interface BeanFactoryPostProcessor {
void postProcessBeanFactory(ConfigurableListableBeanFactory var1) throws BeansException;
}
此接⼝只提供了⼀个⽅法,⽅法参数为ConfigurableListableBeanFactory,该参数类型定义了⼀些⽅法
其中有个⽅法名为getBeanDefinition的⽅法,我们可以根据此⽅法,找到我们定义bean 的BeanDefinition对象。然后我们可以对定义的属性进⾏修改,以下是BeanDefinition中的⽅法