先看一个例子
public class TestBean implements InitializingBean {
@PostConstruct
public void postConstruct() {
System.out.println("postConstruct...");
}
@Override
public void afterPropertiesSet() throws Exception {
System.out.println("afterPropertiesSet...");
}
public void initMethod(){
System.out.println("initMethod...");
}
}
@Configuration(proxyBeanMethods = false)
public class TestConfig {
@Bean(initMethod = "initMethod")
public TestBean testBean() {
return new TestBean();
}
}
输出如下
postConstruct...
afterPropertiesSet...
initMethod...
所以顺序为@PostConstruct > InitializingBean > initMethod
创建Bean的过程中分为三步
- 实例化,:AbstractAutowireCapableBeanFactory#createBeanInstance
- 填充属性:AbstractAutowireCapableBeanFactory#populateBean
- 初始化:AbstractAutowireCapableBeanFactory#initializeBean
这里应该关注初始化阶段,也就是initializeBean方法
直接debug定位到对testBean的处理
注意BeanPostProcessor中有个CommonAnnotationBeanPostProcessor
@PostConstruct就是在这里面处理的
CommonAnnotationBeanPostProcessor的部分继承关系如下
顶层BeanPostProcessor中的两个方法(前置处理和后置处理),在InitDestroyAnnotationBeanPostProcessor中被重写
看名字就大概知道是和初始化销毁相关的处理器
前置处理如下
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
LifecycleMetadata metadata = findLifecycleMetadata(bean.getClass());
try {
metadata.invokeInitMethods(bean, beanName);
}
catch (InvocationTargetException ex) {
throw new BeanCreationException(beanName, "Invocation of init method failed", ex.getTargetException());
}
catch (Throwable ex) {
throw new BeanCreationException(beanName, "Failed to invoke init method", ex);
}
return bean;
}
findLifecycleMetadata => buildLifecycleMetadata
这个方法意义很明确,就是看类中有没有initAnnotationType和destroyAnnotationType类型的注解,
有的话分别加入到initMethods和destroyMethods中,最后构造一个生命周期元数据(LifecycleMetadata)返回
private LifecycleMetadata buildLifecycleMetadata(final Class<?> clazz) {
if (!AnnotationUtils.isCandidateClass(clazz, Arrays.asList(this.initAnnotationType, this.destroyAnnotationType))) {
return this.emptyLifecycleMetadata;
}
List<LifecycleElement> initMethods = new ArrayList<>();
List<LifecycleElement> destroyMethods = new ArrayList<>();
Class<?> targetClass = clazz;
do {
final List<LifecycleElement> currInitMethods = new ArrayList<>();
final List<LifecycleElement> currDestroyMethods = new ArrayList<>();
ReflectionUtils.doWithLocalMethods(targetClass, method -> {
if (this.initAnnotationType != null && method.isAnnotationPresent(this.initAnnotationType)) {
LifecycleElement element = new LifecycleElement(method);
currInitMethods.add(element);
if (logger.isTraceEnabled()) {
logger.trace("Found init method on class [" + clazz.getName() + "]: " + method);
}
}
if (this.destroyAnnotationType != null && method.isAnnotationPresent(this.destroyAnnotationType)) {
currDestroyMethods.add(new LifecycleElement(method));
if (logger.isTraceEnabled()) {
logger.trace("Found destroy method on class [" + clazz.getName() + "]: " + method);
}
}
});
initMethods.addAll(0, currInitMethods);
destroyMethods.addAll(currDestroyMethods);
targetClass = targetClass.getSuperclass();
}
while (targetClass != null && targetClass != Object.class);
return (initMethods.isEmpty() && destroyMethods.isEmpty() ? this.emptyLifecycleMetadata :
new LifecycleMetadata(clazz, initMethods, destroyMethods));
}
initAnnotationType和destroyAnnotationType是InitDestroyAnnotationBeanPostProcessor中的两个属性
在
@Nullable
private Class<? extends Annotation> initAnnotationType;
@Nullable
private Class<? extends Annotation> destroyAnnotationType;
在CommonAnnotationBeanPostProcessor的构造函数中分别设置为PostConstruct和PreDestory
public CommonAnnotationBeanPostProcessor() {
setOrder(Ordered.LOWEST_PRECEDENCE - 3);
setInitAnnotationType(PostConstruct.class);
setDestroyAnnotationType(PreDestroy.class);
ignoreResourceType("javax.xml.ws.WebServiceContext");
// java.naming module present on JDK 9+?
if (jndiPresent) {
this.jndiFactory = new SimpleJndiBeanFactory();
}
}
接着回到一开始的InitDestroyAnnotationBeanPostProcessor#postProcessBeforeInitialization
然后执行invokeInitMethods
就是取出上一步所有的initMethods进行反射调用
也就是执行@PostConstruct标注的方法
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
// 以上已分析过
LifecycleMetadata metadata = findLifecycleMetadata(bean.getClass());
try {
metadata.invokeInitMethods(bean, beanName);
}
catch (InvocationTargetException ex) {
throw new BeanCreationException(beanName, "Invocation of init method failed", ex.getTargetException());
}
catch (Throwable ex) {
throw new BeanCreationException(beanName, "Failed to invoke init method", ex);
}
return bean;
}
public void invokeInitMethods(Object target, String beanName) throws Throwable {
Collection<LifecycleElement> checkedInitMethods = this.checkedInitMethods;
Collection<LifecycleElement> initMethodsToIterate =
(checkedInitMethods != null ? checkedInitMethods : this.initMethods);
if (!initMethodsToIterate.isEmpty()) {
for (LifecycleElement element : initMethodsToIterate) {
if (logger.isTraceEnabled()) {
logger.trace("Invoking init method on bean '" + beanName + "': " + element.getMethod());
}
element.invoke(target);
}
}
}
到这里就可以知道,@PostConstruct是在CommonAnnotationBeanPostProcessor(InitDestroyAnnotationBeanPostProcessor)的postProcessBeforeInitialization(初始化前置)中处理的
回到AbstractAutowireCapableBeanFactory#initializeBean
以上是处理了applyBeanPostProcessorsBeforeInitialization
紧接着下面就是invokeInitMethods(初始化)和applyBeanPostProcessorsAfterInitialization(初始化后置)
protected Object initializeBean(String beanName, Object bean, @Nullable RootBeanDefinition mbd) {
// ...
Object wrappedBean = bean;
if (mbd == null || !mbd.isSynthetic()) {
// 初始化前置处理
// 执行@PostConstruct
wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
}
try {
// 初始化
// 执行InitializingBean#afterPropertiesSet,initMethod
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;
}
invokeInitMethods方法中分成两部分
- 调用InitializingBean#afterPropertiesSet
- 调用自定义的initMethod
protected void invokeInitMethods(String beanName, Object bean, @Nullable RootBeanDefinition mbd)
throws Throwable {
boolean isInitializingBean = (bean instanceof InitializingBean);
if (isInitializingBean && (mbd == null || !mbd.hasAnyExternallyManagedInitMethod("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.hasAnyExternallyManagedInitMethod(initMethodName)) {
invokeCustomInitMethod(beanName, bean, mbd);
}
}
}
参考
https://www.cnblogs.com/april-chen/p/8182631.html
https://developer.aliyun.com/article/766880