Spring初始化对象几种自定义实现方式以及执行顺序
一、实现方式
1.@PostConstruct
2.实现InitializingBean接口
3.@Bean(initMethod = “XX”)指定
4.实现BeanPostProcessor接口
二、执行顺序
1.测试
定义一个user对象 分别实现这几种方式
public class User implements InitializingBean, DisposableBean {
private String name;
public User() {
System.out.println("这是无参构造");
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@PostConstruct
public void postConstruct(){
System.out.println("这是@PostConstruct注解标注得方法");
}
@PreDestroy
public void preDestroy(){
System.out.println("这是@PreDestroy注解标注得方法");
}
@Override
public void afterPropertiesSet() throws Exception {
System.out.println("这是InitializingBean接口中得afterPropertiesSet方法");
}
@Override
public void destroy() throws Exception {
System.out.println("这是DisposableBean接口中destroy方法");
}
public void userInit(){
System.out.println("这是user对象中自定义userInit方法");
}
public void userDestroy(){
System.out.println("这是user对象中自定义userDestroy方法");
}
}
将user对象注册到容器中,指定初始化方法
@Configuration(proxyBeanMethods = false)
public class Config {
@Bean(initMethod = "userInit",destroyMethod = "userDestroy")
public User user(){
User user = new User();
return user;
}
}
自定义Processor 实现BeanPostProcessor接口,因为容器在创建对象时会调用多次该接口实现类方法,因此只在创建user对象时打印
@Component
public class MyPostProcessor implements BeanPostProcessor {
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
if(bean instanceof User){
System.out.println("这是BeanPostProcessor接口中得postProcessBeforeInitialization");
}
return bean;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
if(bean instanceof User){
System.out.println("这是BeanPostProcessor接口中得postProcessAfterInitialization");
}
return bean;
}
}
2.输出结果
这是无参构造
这是BeanPostProcessor接口中得postProcessBeforeInitialization
这是@PostConstruct注解标注得方法
这是InitializingBean接口中得afterPropertiesSet方法
这是user对象中自定义userInit方法
这是BeanPostProcessor接口中得postProcessAfterInitialization
这是@PreDestroy注解标注得方法
这是DisposableBean接口中destroy方法
这是user对象中自定义userDestroy方法
3.分析原因
直接看源码
//该方法为初始化bean 在此之前已经创建好了对象 因此先执行user对象的无参构造
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()) {
//此处遍历所有后置处理器,执行postProcessBeforeInitialization方法
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()) {
//此处遍历所有后置处理器,执行postProcessAfterInitialization方法
wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
}
return wrappedBean;
}
public Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName)
throws BeansException {
Object result = existingBean;
for (BeanPostProcessor processor : getBeanPostProcessors()) {
//这里遍历所有的后置处理器 执行postProcessBeforeInitialization方法
//后置处理器包含我们自定义的MyPostProcessor以及使用@PostConstruct标注的方法(标注该注解的就是该类CommonAnnotationBeanPostProcessor解析的)
//因此按遍历顺序分别执行了MyPostProcessor和@PostConstruct
Object current = processor.postProcessBeforeInitialization(result, beanName);
if (current == null) {
return result;
}
result = current;
}
return result;
}
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 {
//此处调用了实现了InitializingBean接口中得afterPropertiesSet方法
AccessController.doPrivileged((PrivilegedExceptionAction<Object>) () -> {
((InitializingBean) bean).afterPropertiesSet();
return null;
}, getAccessControlContext());
}
catch (PrivilegedActionException pae) {
throw pae.getException();
}
}
else {
((InitializingBean) bean).afterPropertiesSet();
}
}
//此处执行@baen注解中的initMethod = "userInit"方法
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);
}
}
}
public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)
throws BeansException {
Object result = existingBean;
for (BeanPostProcessor processor : getBeanPostProcessors()) {
//此处执行我们自定义的MyPostProcessor的postProcessAfterInitialization方法
Object current = processor.postProcessAfterInitialization(result, beanName);
if (current == null) {
return result;
}
result = current;
}
return result;
}