只需低头努力,剩下的交给时光,时间会公平地帮你处理一切
BeanPostProcessor是Bean的后置处理器,在spring容器启动的过程中,会调用BeanPostProcessor中的方法来进行Bean的处理。
BeanPostProcessor接口中有两个方法:
public interface BeanPostProcessor {
@Nullable
default Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
return bean;
}
@Nullable
default Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
return bean;
}
}
从两个方法名就可以看出来,postProcessBeforeInitialization是在初始化之前调用,postProcessAfterInitialization是在初始化之后调用
需要注意的是,这两个方法都有default实现,默认实现是直接返回Bean,不对Bean做任何处理
关于接口的default实现方法,可以参考我的另外一篇博文《Java接口原来还可以这么玩》
源码分析
关于BeanPostProcessor的处理是在AbstractAutowireCapableBeanFactory中的initializeBean方法中
protected Object initializeBean(final String beanName, final Object bean, @Nullable RootBeanDefinition mbd) {
if (System.getSecurityManager() != null) {
AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
invokeAwareMethods(beanName, bean);
return null;
}, getAccessControlContext());
}
else {
invokeAwareMethods(beanName, bean);
}
Object wrappedBean = bean;
if (mbd == null || !mbd.isSynthetic()) {
wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
}
try {
invokeInitMethods(beanName, wrappedBean, mbd);
}
catch (Throwable ex) {
throw new BeanCreationException(
(mbd != null ? mbd.getResourceDescription() : null),
beanName, "Invocation of init method failed", ex);
}
if (mbd == null || !mbd.isSynthetic()) {
wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
}
return wrappedBean;
}
在initializeBean方法中会在invokeInitMethods方法调用之前、之后分别调用applyBeanPostProcessorsBeforeInitialization和applyBeanPostProcessorsAfterInitialization,这两个方法就是用来处理BeanPostProcessor的,下面具体看一下:
public Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName)
throws BeansException {
Object result = existingBean;
for (BeanPostProcessor processor : getBeanPostProcessors()) {
Object current = processor.postProcessBeforeInitialization(result, beanName);
if (current == null) {
return result;
}
result = current;
}
return result;
}
public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)
throws BeansException {
Object result = existingBean;
for (BeanPostProcessor processor : getBeanPostProcessors()) {
Object current = processor.postProcessAfterInitialization(result, beanName);
if (current == null) {
return result;
}
result = current;
}
return result;
}
这两个方法的逻辑很简单,都是循环调用BeanPostProcessor的方法,只不过一个是调用postProcessBeforeInitialization方法,一个是调用postProcessAfterInitialization方法
也就是说在initializeBean方法中调用invokeInitMethods方法之前会调用postProcessBeforeInitialization,调用invokeInitMethods之后会调用postProcessAfterInitialization方法,那我们一起来看看invokeInitMethods方法是干啥的
protected void invokeInitMethods(String beanName, final Object bean, @Nullable RootBeanDefinition mbd)
throws Throwable {
boolean isInitializingBean = (bean instanceof InitializingBean);
if (isInitializingBean && (mbd == null || !mbd.isExternallyManagedInitMethod("afterPropertiesSet"))) {
if (logger.isTraceEnabled()) {
logger.trace("Invoking afterPropertiesSet() on bean with name '" + beanName + "'");
}
if (System.getSecurityManager() != null) {
try {
AccessController.doPrivileged((PrivilegedExceptionAction<Object>) () -> {
((InitializingBean) bean).afterPropertiesSet();
return null;
}, getAccessControlContext());
}
catch (PrivilegedActionException pae) {
throw pae.getException();
}
}
else {
((InitializingBean) bean).afterPropertiesSet();
}
}
if (mbd != null && bean.getClass() != NullBean.class) {
String initMethodName = mbd.getInitMethodName();
if (StringUtils.hasLength(initMethodName) &&
!(isInitializingBean && "afterPropertiesSet".equals(initMethodName)) &&
!mbd.isExternallyManagedInitMethod(initMethodName)) {
invokeCustomInitMethod(beanName, bean, mbd);
}
}
}
invokeInitMethods方法的逻辑也很清晰,做了两件事
- 判断是不是InitializingBean,是的话就调用afterPropertiesSet
- 判断是否有自己定义的initMethod,有的话就调用对应的方法
这是主线逻辑,忽略了很多细节,在看源码的时候注意甄别
从这里我们可以得到一个调用顺序
- BeanPostProcessor->postProcessBeforeInitialization
- InitializingBean -> afterPropertiesSet
- bean -> initMethod
- BeanPostProcessor->postProcessAfterInitialization
下面我们通过一个例子来看一下是不是这样一个调用顺序
一个例子
public class User implements InitializingBean {
public User(String name,int age){
System.out.println("调用构造方法");
this.name = name;
this.age = age;
}
public void initMethod(){
System.out.println("调用Bean -> initMethod");
this.name = "initMethod";
this.age = 3;
}
private String name;
private int age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public void afterPropertiesSet() throws Exception {
System.out.println("调用InitializingBean -> afterPropertiesSet");
this.name = "afterPropertiesSet";
this.age = 4;
}
}
定义了一个User类,实现了InitializingBean接口,覆盖了其afterPropertiesSet方法,User类中有一个带参的构造方法,一个初始化的方法initMethod
public class MyBeanPostProcessor implements BeanPostProcessor {
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
if(bean instanceof User){
((User) bean).setName("postProcessBeforeInitialization");
}
System.out.println("调用BeanPostProcessor -> postProcessBeforeInitialization");
return bean;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
if(bean instanceof User){
((User) bean).setName("postProcessAfterInitialization");
}
System.out.println("调用BeanPostProcessor -> postProcessAfterInitialization");
return bean;
}
}
MyBeanPostProcessor实现BeanPostProcessor接口,并且覆盖了其postProcessBeforeInitialization和postProcessAfterInitialization
@Component
public class Configuration {
@Bean(initMethod = "initMethod")
public User getUser(){
return new User("开心果",2);
}
@Bean
public BeanPostProcessor getBeanPostProcessor(){
return new MyBeanPostProcessor();
}
}
我们将User对象和MyBeanPostProcessor对象注册到Spring容器中,这里注意一下User对象指定了initMethod,对应的就是Spring源码分析中的用户自定义initMethod
public class Main {
public static void main(String[] args){
AnnotationConfigApplicationContext annotationConfigApplicationContext = new AnnotationConfigApplicationContext("org.kxg.springDemo.beanPostProcessor");
User user = annotationConfigApplicationContext.getBean(User.class);
System.out.println(user.getName());
}
}
运行结果如下:
调用构造方法
调用BeanPostProcessor -> postProcessBeforeInitialization
调用InitializingBean -> afterPropertiesSet
调用Bean -> initMethod
调用BeanPostProcessor -> postProcessAfterInitialization
postProcessAfterInitialization
从运行结果中可以看到,所有的方法都是在调用构造方法之后执行的,执行顺序跟我们上面源码中分析的是一致的
总结一下
- BeanPostProcessor是Bean的后置处理器,在spring容器启动的过程中,会调用BeanPostProcessor中的方法来进行Bean的处理
- 调用顺序:
- BeanPostProcessor->postProcessBeforeInitialization
- InitializingBean -> afterPropertiesSet
- bean -> initMethod
- BeanPostProcessor->postProcessAfterInitialization
如果感觉对你有些帮忙,请收藏好,你的关注和点赞是对我最大的鼓励!
如果想跟我一起学习,坚信技术改变世界,请关注【Java天堂】公众号,我会定期分享自己的学习成果,第一时间推送给您