Spring组件生命周期粗略来说有四个阶段:
实例化>属性赋值>初始化>销毁
后置处理器
说到生命周期,不得不提后置处理器,有两个非常重要的接口
InstantiationAwareBeanPostProcessor:主要作用于实例创建前后
BeanPostProcessor:作用于Bean初始化前后
看个图来深刻理解下
后置处理器的使用
BeanPostProcessor
写一个类继承BeanPostProcessor接口,并注册到容器中
/**
*容器初始化Bean都会被该后置处理器影响
*/
@Component
public class MyBeanPostProcessor implements BeanPostProcessor {
/**
* 初始化前执行
* @param bean 注册的Bean
* @param beanName 注册的Bean的name
* @return
* @throws BeansException
*/
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
System.out.println("postProcessBeforeInitialization=>"+beanName);
//可对Bean进行包装处理等工作后返回
return bean;
}
//初始化后执行 其他同上
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
System.out.println("postProcessAfterInitialization=>"+beanName);
return bean;
}
}
这样在Bean初始化前后都会分别打印beanName
InstantiationAwareBeanPostProcessor
通常用于禁止特定目标Bean的默认实例化,例如,使用特殊的TargetSource创建代理(合并目标,延迟初始化目标等),或实施其他注入策略。
写一个类继承BeanPostProcessor接口,并注册到容器中
@Component
public class MyInstantiationAwareBeanPostProcessor implements InstantiationAwareBeanPostProcessor {
/*
返回的bean对象可以是要使用的代理,而不是目标bean,
有效抑制目标Bean的默认实例化。
返回不能为Null否则抛异常。
*/
public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
System.out.println("postProcessBeforeInstantiation=>"+beanName);
return null;
}
/*
此时Bean已经实例化
返回值决定是否要调用 postProcessPropertyValues true调用 否则反之
*/
public boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {
System.out.println("postProcessAfterInstantiation=>"+beanName);
return true;
}
/*
根据需求为Bean赋值
*/
public PropertyValues postProcessPropertyValues(PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) throws BeansException {
System.out.println("postProcessPropertyValues=>"+pvs);
return null;
}
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
System.out.println("postProcessBeforeInitialization=>"+beanName);
return bean;
}
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
System.out.println("postProcessAfterInitialization=>"+beanName);
return bean;
}
}
初始化Ioc容器查看控制台输出内容
在Spring中的运用
后置处理器在Spring中也大量的运用。
举个例子:ApplicationContextAwareProcessor
这是Spring定义获取上下文的后置处理器
下方为ApplicationContextAwareProcessor的源码
class ApplicationContextAwareProcessor implements BeanPostProcessor {
private final ConfigurableApplicationContext applicationContext;
private final StringValueResolver embeddedValueResolver;
/**
* Create a new ApplicationContextAwareProcessor for the given context.
*/
public ApplicationContextAwareProcessor(ConfigurableApplicationContext applicationContext) {
this.applicationContext = applicationContext;
this.embeddedValueResolver = new EmbeddedValueResolver(applicationContext.getBeanFactory());
}
@Override
public Object postProcessBeforeInitialization(final Object bean, String beanName) throws BeansException {
AccessControlContext acc = null;
if (System.getSecurityManager() != null &&
(bean instanceof EnvironmentAware || bean instanceof EmbeddedValueResolverAware ||
bean instanceof ResourceLoaderAware || bean instanceof ApplicationEventPublisherAware ||
bean instanceof MessageSourceAware || bean instanceof ApplicationContextAware)) {
acc = this.applicationContext.getBeanFactory().getAccessControlContext();
}
if (acc != null) {
AccessController.doPrivileged(new PrivilegedAction<Object>() {
@Override
public Object run() {
invokeAwareInterfaces(bean);
return null;
}
}, acc);
}
else {
invokeAwareInterfaces(bean);
}
return bean;
}
private void invokeAwareInterfaces(Object bean) {
if (bean instanceof Aware) {
if (bean instanceof EnvironmentAware) {
((EnvironmentAware) bean).setEnvironment(this.applicationContext.getEnvironment());
}
if (bean instanceof EmbeddedValueResolverAware) {
((EmbeddedValueResolverAware) bean).setEmbeddedValueResolver(this.embeddedValueResolver);
}
if (bean instanceof ResourceLoaderAware) {
((ResourceLoaderAware) bean).setResourceLoader(this.applicationContext);
}
if (bean instanceof ApplicationEventPublisherAware) {
((ApplicationEventPublisherAware) bean).setApplicationEventPublisher(this.applicationContext);
}
if (bean instanceof MessageSourceAware) {
((MessageSourceAware) bean).setMessageSource(this.applicationContext);
}
if (bean instanceof ApplicationContextAware) {
((ApplicationContextAware) bean).setApplicationContext(this.applicationContext);
}
}
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) {
return bean;
}
}
可以看到初始化中调用invokeAwareInterfaces判断bean是否为ApplicationContextAware如果是的话就把上下文传递过去。
只要继承ApplicationContextAware接口就可以获取到上下文。
@Component
public class Animal implements ApplicationContextAware {
private ApplicationContext applicationContext;
//Bean在初始化时前 会被ApplicationContextAwareProcessor调用 从而获得上下文
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
this.applicationContext = applicationContext;
}
}
另外Spring中有大量的Aware结尾的接口,通常这些接口都是可以获取到Spring容器的相关信息的。