Spring初始化Bean的幾種方式
1. 實(shí)現(xiàn)InitializingBean接口,重寫afterPropertiesSet方法
2. <Bean>元素上添加init-method初始化
3. 使用@PostConstruct注解
執(zhí)行順序:Constructor > @PostConstruct > InitializingBean > init-method
源碼位置
AbstractAutowireCapableBeanFactory#initializeBean
protected Object initializeBean(final String beanName, final Object bean, @Nullable RootBeanDefinition mbd) {
// ...
Object wrappedBean = bean;
if (mbd == null || !mbd.isSynthetic()) {
// 初始化前置處理
wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
}
try {
// 調(diào)用初始化方法
invokeInitMethods(beanName, wrappedBean, mbd);
} catch (Throwable ex) {
// ...
}
if (mbd == null || !mbd.isSynthetic()) {
// 初始化后置處理
wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
}
return wrappedBean;
}
這里主要包含了初始化的前置處理、調(diào)用初始化方法、初始化后置處理
@PostConstruct
@PostConstruct注解將在applyBeanPostProcessorsBeforeInitialization這個前置處理
@Override
public Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName)
throws BeansException {
Object result = existingBean;
for (BeanPostProcessor beanProcessor : getBeanPostProcessors()) {
Object current = beanProcessor.postProcessBeforeInitialization(result, beanName);
if (current == null) {
return result;
}
result = current;
}
return result;
}
跟進(jìn)InitDestroyAnnotationBeanPostProcessor#postProcessBeforeInitialization方法
@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方法會解析元數(shù)據(jù),所以@PostConstruct注解的初始化方法在這里找到了。
再跟進(jìn)findLifecycleMetadata方法
@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;
}
再進(jìn)findLifecycleMetadata
private LifecycleMetadata findLifecycleMetadata(Class<?> clazz) {
if (this.lifecycleMetadataCache == null) {
// Happens after deserialization, during destruction...
return buildLifecycleMetadata(clazz);
}
// Quick check on the concurrent map first, with minimal locking.
LifecycleMetadata metadata = this.lifecycleMetadataCache.get(clazz);
if (metadata == null) {
synchronized (this.lifecycleMetadataCache) {
metadata = this.lifecycleMetadataCache.get(clazz);
if (metadata == null) {
metadata = buildLifecycleMetadata(clazz);
this.lifecycleMetadataCache.put(clazz, metadata);
}
return metadata;
}
}
return metadata;
}
再進(jìn)buildLifecycleMetadata
private LifecycleMetadata buildLifecycleMetadata(final Class<?> clazz) {
final boolean debug = logger.isDebugEnabled();
LinkedList<LifecycleElement> initMethods = new LinkedList<>();
LinkedList<LifecycleElement> destroyMethods = new LinkedList<>();
Class<?> targetClass = clazz;
do {
final LinkedList<LifecycleElement> currInitMethods = new LinkedList<>();
final LinkedList<LifecycleElement> currDestroyMethods = new LinkedList<>();
ReflectionUtils.doWithLocalMethods(targetClass, method -> {
if (initAnnotationType != null && method.isAnnotationPresent(initAnnotationType)) {
LifecycleElement element = new LifecycleElement(method);
currInitMethods.add(element);
if (debug) {
logger.debug("Found init method on class [" + clazz.getName() + "]: " + method);
}
}
if (destroyAnnotationType != null && method.isAnnotationPresent(destroyAnnotationType)) {
currDestroyMethods.add(new LifecycleElement(method));
if (debug) {
logger.debug("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 new LifecycleMetadata(clazz, initMethods, destroyMethods);
}
可以看到有個判斷是否被initAnnotationType注釋注解,然后添加到集合中。
initAnnotationType位于CommonAnnotationBeanPostProcessor類中
public CommonAnnotationBeanPostProcessor() {
setOrder(Ordered.LOWEST_PRECEDENCE - 3);
setInitAnnotationType(PostConstruct.class);
setDestroyAnnotationType(PreDestroy.class);
ignoreResourceType("javax.xml.ws.WebServiceContext");
}

可以看到CommonAnnotationBeanPostProcessor和InitDestroyAnnotationBeanPostProcessor的關(guān)系是繼承關(guān)系
實(shí)現(xiàn)InitializingBean接口afterPropertiesSet方法
繼續(xù)initializeBean方法,這次來看invokeInitMethods方法
protected Object initializeBean(final String beanName, final Object bean, @Nullable RootBeanDefinition mbd) {
.....
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;
}
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.isDebugEnabled()) {
logger.debug("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);
}
}
}
可以看出首先會檢查是否是InitializingBean,如果是調(diào)用afterPropertiesSet()方法
init-method
在invokeInitMethods方法中,我們會發(fā)現(xiàn)以下這段代碼,它是執(zhí)行init-method配置的內(nèi)容
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);
}
}
postProcessAfterInitialization方法
再次回到initializeBean方法,可以看到最后調(diào)用了applyBeanPostProcessorsAfterInitialization方法
@Override
public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)
throws BeansException {
Object result = existingBean;
for (BeanPostProcessor beanProcessor : getBeanPostProcessors()) {
Object current = beanProcessor.postProcessAfterInitialization(result, beanName);
if (current == null) {
return result;
}
result = current;
}
return result;
}
總結(jié)
根據(jù)上述源碼可以得出以下執(zhí)行順序:postProcessBeforeInitialization->InitializingBean(afterPropertiesSet)->init-method->postProcessAfterInitialization
BeanPostProcessor后置處理器
如果一個Bean實(shí)現(xiàn)了BeanPostProcess接口,將會調(diào)用postProcessBeforeInitialization(Object bean, String beanName)方法,
經(jīng)常用于對Bean內(nèi)容的更改,并且由于這個在Bean初始化結(jié)束時調(diào)用,也常被應(yīng)用與緩存或者內(nèi)存技術(shù)
postProcessBeforeInitialization方法在bean初始化之前執(zhí)行, postProcessAfterInitialization方法在bean初始化之后執(zhí)行