Spring 之 InstantiationAwareBeanPostProcessor 接口
Spring 之 InstantiationAwareBeanPostProcessor 接口
1、简介
InstantiationAwareBeanPostProcessor 接口是 BeanPostProcessor 的子接口,通过接口字面意思翻译该接口的作用是对 Bean实例化的处理器。
接口源码如下:
public interface InstantiationAwareBeanPostProcessor extends BeanPostProcessor {
/**
* bean 实例化之前钩子
*/
@Nullable
default Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
return null;
}
/**
* bean 实例化之后的钩子
*/
default boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {
return true;
}
/**
* bean 实例化之后 且postProcessAfterInstantiation返回true 执行bean的属性操作的钩子
*/
@Nullable
default PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName)
throws BeansException {
return null;
}
}
2、使用示例:
2.1、创建接口实现类 MyInstantiationAwareBeanPostProcessor
/**
* @Author dw
* @ClassName MyInstantiationAwareBeanPostProcessor
* @Description
* @Date 2021/12/11 21:16
* @Version 1.0
*/
@Component
public class MyInstantiationAwareBeanPostProcessor implements InstantiationAwareBeanPostProcessor {
/**
* InstantiationAwareBeanPostProcessor中自定义的方法
* 在方法实例化之前执行 Bean对象还没有
* 如果不需要对实例化之前的bean进行替换,可以返回null
*/
@Override
public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
System.out.println("postProcessBeforeInstantiation..." + beanName);
return null;
}
/**
* InstantiationAwareBeanPostProcessor中自定义的方法
* 在方法实例化之后执行 Bean对象已经创建出来了
*/
@Override
public boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {
System.out.println("postProcessAfterInstantiation..." + beanName);
return true;
}
/**
* InstantiationAwareBeanPostProcessor中自定义的方法
* 可以用来修改Bean中属性的内容
*/
@Override
public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) throws BeansException {
System.out.println("postProcessProperties..." + beanName);
return pvs;
}
/**
* BeanPostProcessor接口中的方法
* 在Bean的自定义初始化方法之前执行
* Bean对象已经存在了,不能返回null, 否则会报NullPointerException
*/
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
System.out.println("postProcessBeforeInitialization..." + beanName);
return bean;
}
/**
* BeanPostProcessor接口中的方法
* 在Bean的自定义初始化方法执行完成之后执行
* Bean对象已经存在了,不能返回null, 否则会报NullPointerException
*/
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
System.out.println("postProcessAfterInitialization..." + beanName);
return bean;
}
}
2.2:创建bean : MyUser
@Data
public class MyUser {
private String userName;
private Integer userAge;
private UserRole userRole;
}
@Configuration
public class MyBeanConfig {
@Bean
public MyUser myUser(){
return new MyUser();
}
}
启动项目发现控制台会打印一堆的如下输出, 说明实现了该接口后, 对容器中的大部分 bean 都有效。
postProcessBeforeInstantiation...myUser
postProcessAfterInstantiation...myUser
postProcessProperties...myUser
postProcessBeforeInitialization...myUser
postProcessAfterInitialization...myUser
3、分析相关方法
3.1、postProcessBeforeInstantiation
该方法返回的结果如果为null,后面的方法都正常执行了,但是如果该方法返回了实例对象了呢?我们来看下
修改 postProcessBeforeInstantiation:
@Override
public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
System.out.println("postProcessBeforeInstantiation...");
if (beanName.equals("myUser")) {
return new MyUser();
}
return null;
}
控制台输出如下:
postProcessBeforeInstantiation...myUser
postProcessAfterInitialization...myUser
通过数据结果我们发现,postProcessBeforeInstantiation方法返回实例对象后跳过了对象的初始化操作,直接执行了postProcessAfterInitialization,跳过了postProcessAfterInstantiation,postProcessPropertyValues,为什么会这样呢?我们要来查看下源代码。
在AbstractAutowireCapableBeanFactory类中有个createBean方法:
protected Object createBean(String beanName, RootBeanDefinition mbd, Object[] args) throws BeanCreationException {
// ... 省略
try {
// Give BeanPostProcessors a chance to return a proxy instead of the target bean instance.
Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
if (bean != null) {
return bean;
}
// ... 省略
Object beanInstance = doCreateBean(beanName, mbdToUse, args);
if (logger.isDebugEnabled()) {
logger.debug("Finished creating instance of bean '" + beanName + "'");
}
return beanInstance;
}
4、总结:
如果postProcessBeforeInstantiation方法返回了Object是null; 那么就直接调用doCreateBean方法();
如果postProcessBeforeInstantiation返回不为null;说明修改了bean对象;然后这个时候就立马执行postProcessAfterInitialization方法(注意这个是初始化之后的方法,也就是通过这个方法实例化了之后,直接执行初始化之后的方法;中间的实例化之后 和 初始化之前都不执行);
个人觉得这个接口只有这个方法 postProcessBeforeInstantiation 有点用, 其余两个方法并没有啥用。SpringAop的实现就是基于InstantiationAwareBeanPostProcessor 的postProcessBeforeInstantiation 这个方法使用代理替换了原有的对象实例。
5、InstantiationAwareBeanPostProcessor 执行流程、时机分析
org.springframework.context.support.AbstractApplicationContext#refresh
org.springframework.context.support.AbstractApplicationContext#finishBeanFactoryInitialization
org.springframework.beans.factory.support.DefaultListableBeanFactory#preInstantiateSingletons
org.springframework.beans.factory.support.AbstractBeanFactory#doGetBean
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#createBean
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#resolveBeforeInstantiation
回到 org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#createBean 如果 org.springframework.beans.factory.config.InstantiationAwareBeanPostProcessor#postProcessBeforeInstantiation 没有返回代理对象实例,则走普通Bean的创建逻辑。
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#doCreateBean
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#initializeBean