结论
答案是可以的。
Talk is cheap. Show me the code
第一步:定义一个类实现任意Spring中Bean生命周期相关方法。
package com.xxx.hyl.ignore.lifecycle;
import org.springframework.beans.factory.InitializingBean;
/***
* 演示当前类跳过Spring IoC 容器Bean生命周期管理
* @author 君战
* */
public class IgnoreLifecycleBean implements InitializingBean {
private String createdBy;
// 这里只是为了演示,所以只选择实现InitializingBean接口,只要该接口可以跳过,其它的生命周期方法都是一样的。
@Override
public void afterPropertiesSet() throws Exception {
System.out.println(this.getClass().getSimpleName() + " -----> afterPropertiesSet 方法执行");
}
public String getCreatedBy() {
return createdBy;
}
public void setCreatedBy(String createdBy) {
this.createdBy = createdBy;
}
}
第二步:编写一个类实现InstantiationAwareBeanPostProcessor接口,并重写其postProcessBeforeInstantiation方法。
package com.xxx.hyl.ignore.lifecycle;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.InstantiationAwareBeanPostProcessor;
/**
* 演示通过实现{@linkplain InstantiationAwareBeanPostProcessor#postProcessBeforeInstantiation(Class,
* String)} 方法来让Bean跳过IoC容器生命周期管理
*
* @author 君战 *
*/
public class CustomizedBeanPostProcessor implements InstantiationAwareBeanPostProcessor {
@Override
public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName)
throws BeansException {
if (IgnoreLifecycleBean.class.equals(beanClass)) {
IgnoreLifecycleBean ignoreLifecycleBean = new IgnoreLifecycleBean();
ignoreLifecycleBean.setCreatedBy("customize init");
return ignoreLifecycleBean;
}
return null;
}
}
第三步:编写一个类来测试
package com.xxx.hyl.ignore.lifecycle;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
/**
* 演示Bean跳过IoC容器的生命周期管理
* @author 君战
* **/
public class IgnoreLifecycleBeanDemo {
public static void main(String[] args) {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
context.register(IgnoreLifecycleBean.class,CustomizedBeanPostProcessor.class);
context.refresh();
IgnoreLifecycleBean ignoreLifecycleBean = context.getBean(IgnoreLifecycleBean.class);
System.out.println(ignoreLifecycleBean.getCreatedBy());
}
}
第四步:查看控制台打印结果。
底层原理分析
在AbstractAutowireCapableBeanFactory的createBean方法中,首先通过resolveBeanClass方法来解析BeanDefinition,获取要实例化的BeanClass。然后调用RootBeanDefinition的prepareMethodOverrides方法,重点是接下来调用的resolveBeforeInstantiation方法,可以看到如果该方法的返回值不为空,则createBean方法结束,而不会再去调用IoC容器中真正实例化Bean的方法-doCreateBean。
// AbstractAutowireCapableBeanFactory#createBean(java.lang.String, org.springframework.beans.factory.support.RootBeanDefinition, java.lang.Object[])
protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
throws BeanCreationException {
if (logger.isTraceEnabled()) {
logger.trace("Creating instance of bean '" + beanName + "'");
}
RootBeanDefinition mbdToUse = mbd;
Class<?> resolvedClass = resolveBeanClass(mbd, beanName);
if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) {
mbdToUse = new RootBeanDefinition(mbd);
mbdToUse.setBeanClass(resolvedClass);
}
try {
mbdToUse.prepareMethodOverrides();
}
catch (BeanDefinitionValidationException ex) {
throw new BeanDefinitionStoreException(mbdToUse.getResourceDescription(),
beanName, "Validation of method overrides failed", ex);
}
try {
// 调用所有实现了InstantiationAwareBeanPostProcessor接口的postProcessBeforeInstantiation方法
// 任何一个InstantiationAwareBeanPostProcessor接口实现类的postProcessBeforeInstantiation方法返回值不为null,那么则结束当前beanName所对应Bean的创建和初始化。
Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
if (bean != null) {
return bean;
}
}
catch (Throwable ex) {
throw new BeanCreationException(mbdToUse.getResourceDescription(), beanName,
"BeanPostProcessor before instantiation of bean failed", ex);
}
try {
// 这是IoC容器真正实例化Bean的地方
Object beanInstance = doCreateBean(beanName, mbdToUse, args);
if (logger.isTraceEnabled()) {
logger.trace("Finished creating instance of bean '" + beanName + "'");
}
return beanInstance;
}
catch (BeanCreationException | ImplicitlyAppearedSingletonException ex) {
throw ex;
}
catch (Throwable ex) {
throw new BeanCreationException(
mbdToUse.getResourceDescription(), beanName, "Unexpected exception during bean creation", ex);
}
}
而讲到这个resolveBeforeInstantiation方法,就不得不提InstantiationAwareBeanPostProcessor接口,该接口继承自Spring IoC容器中大名鼎鼎的BeanPostProcessor接口,并定义了四个接口方法-postProcessBeforeInstantiation方法和postProcessAfterInstantiation方法以及postProcessProperties方法和postProcessPropertyValues方法(该方法已被标记为废弃)。
而前面的resolveBeforeInstantiation方法就是调用IoC容器中所有实现了该接口的实现类的postProce-ssBeforeInstantiation方法,入参为前面解析好的BeanClass和beanName,如果有某一个实现类实现的该方法返回了数据,则直接结束循环,当前Bean的整个实例化过程就结束了。Bean中所有的依赖项、生命周期相关的方法都不会再被处理,因此,很少会有处理器在该方法中返回数据。
// AbstractAutowireCapableBeanFactory#applyBeanPostProcessorsBeforeInstantiation
protected Object resolveBeforeInstantiation(String beanName, RootBeanDefinition mbd) {
Object bean = null;
if (!Boolean.FALSE.equals(mbd.beforeInstantiationResolved)) {
// Make sure bean class is actually resolved at this point.
if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
Class<?> targetType = determineTargetType(beanName, mbd);
if (targetType != null) {
bean = applyBeanPostProcessorsBeforeInstantiation(targetType, beanName);
if (bean != null) {
bean = applyBeanPostProcessorsAfterInitialization(bean, beanName);
}
}
}
mbd.beforeInstantiationResolved = (bean != null);
}
return bean;
}
protected Object applyBeanPostProcessorsBeforeInstantiation(Class<?> beanClass, String beanName) {
for (BeanPostProcessor bp : getBeanPostProcessors()) {
if (bp instanceof InstantiationAwareBeanPostProcessor) {
InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
Object result = ibp.postProcessBeforeInstantiation(beanClass, beanName);
if (result != null) {
return result;
}
}
}
return null;
}
总结
Spring中的Bean是可以绕过IoC容器的Bean生命周期管理的,只需要实现InstantiationAwareBeanPostProcessor接口并重写其postProcessBeforeInstantiation方法来对指定beanClass进行创建,从而绕过IoC容器的生命周期管理。
但请慎用该手段,因为通过这种方式返回的Bean不仅其生命周期不受IoC容器管理,并且其依赖也不会被IoC容器所处理。如果其处于切点表达式的指定范围内,那么也不会被进行增强(动态代理/字节码增强),其方法上@Transactional注解将失去作用等等。
慎用!慎用!慎用!