Spring bean生命周期之doCreateBean方法详解
Spring bean生命周期之doCreateBean方法详解
前言
在上一篇笔记中我们介绍了bean的初始化声明周期,但是期间有个最核心的方法createBean没有讲,这个方法是如果在创建bean的过程中,没有找到对应的ban对象,那么最后就会调用createBean方法,createBean方法中包含了很多bean实例化和初始化、aware的调用以及spring内置的一些beanPostProcessor方法调用的一些过程,可以算是最核心的方法,我认为的是在spring的声明周期中 ,这个方法算是比较重要的,也是比较绕的,在spring的ioc容器中,我觉得是分为三个比较重要的部分,第一个部分就是通过asm技术扫描类的全限定名到BeanDefinition中的beanclass中,第二个主要的过程就是BeanFactoryPostProcessor的后置处理器,也就是bean工厂的后置处理器,第三个过程就是bean的BeanPostProcessor,bean后置处理器,特别是beanPostProcessor里面有很多spring内置的bean后置处理器,比如bean的实例化前、实例化、实例化后,属性填充后、初始化前、初始化、初始化后这些过程都是bean的后置处理器去完成的,当然了我们也根据编写自己的后置处理器,自己编写的后置处理器只需要继承spring的beanPostProcessor或者其他继承了BeanPostProcessor后置处理器就可实现了,所以spring在上面的6个过程中调用的后置处理器都会执行,就是程序员自己定义的后置处理器和spring内部的后置处理器都要执行,所以spring的bean后置处理器非常重要,也是spring的扩展点之一,我们熟知的大名鼎鼎的Spring Aop也就是使用了spring的Bean后置处理器,Spring AOP是在spring初始化完成后调用的后置处理器,也就是初始化后的后置处理器,这个后面有时间再记录,今天主要记录下spring的createBean方法,也就是大量的后置处理器来了,createBean方法的入口是在geBean的时候,如果经过一系列的方法都没有找到对应的Bean过后就会调用,入口如下:
@Value
在讲解createBean方法之前,我们来看一个很有意思的东西,可能大部分都不知道,就是我们在一个bean中声明了另外一个bean,通常一般的做法是通过@AutoWired来进行注入的,但是有没有人是否知道其实还可以通过@Value来注入的,比如:
@Component
public class UserService {
@Value("#{orderService}")
private OrderService orderService;
@Autowired
private OrderService orderService1;
public void test(){
System.out.println("@Value="+orderService);
System.out.println("@AutoWried="+orderService1);
}
}
输出的是:
@Value=com.bml10.service.OrderService@28864e92
@AutoWried=com.bml10.service.OrderService@28864e92
所以通过@Value也可以进行注入的,但是要注意@Value的注入方式和@AutoWried是不对等的,@Value是直接去单例池给你找到注入进去,而@AutoWired是先byType,再byName的,而且还要注意的是@Value中如果直接使用的是字符串,那么就会将这个字符串直接注入到属性上,如果是$占位符,那么就会获取Environment中的属性参数赋值过去,只有表达式是#,el表达式,spring才会从单例池中获取bean对象进行注入。
createBean方法详解
我这边现在直接上我在源码中编写的注释和源码,如下
/**
* Central method of this class: creates a bean instance,
* populates the bean instance, applies post-processors, etc.
* @see #doCreateBean
* 这个方法特别复杂,是spring容器创建bean和获取Bean的核心方法
*/
@Override
protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
throws BeanCreationException {
if (logger.isTraceEnabled()) {
logger.trace("Creating instance of bean '" + beanName + "'");
}
//到这个方法创建Bean的时候beanDefinition的类型必须是RootBeanDefinition
//RootBeanDefinition是*的父类BeanDefinition,是不允许再有父亲的BeanDefinition的
//在调用这个方法之前,是会进行BeanDefinition的封装和合并的
RootBeanDefinition mbdToUse = mbd;
// Make sure bean class is actually resolved at this point, and
// clone the bean definition in case of a dynamically resolved Class
// which cannot be stored in the shared merged bean definition.
//加载beanclass,将bean的class拿出来加载到jvm中
Class<?> resolvedClass = resolveBeanClass(mbd, beanName);
if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) {
//加载成功过后,然后创建一个对象RootBeanDefinition,这个RootBeanDefinition就是最终创建的单例对象放入到单例池
mbdToUse = new RootBeanDefinition(mbd);
mbdToUse.setBeanClass(resolvedClass);
}
// Prepare method overrides.
try {
mbdToUse.prepareMethodOverrides();
}
catch (BeanDefinitionValidationException ex) {
throw new BeanDefinitionStoreException(mbdToUse.getResourceDescription(),
beanName, "Validation of method overrides failed", ex);
}
try {
// Give BeanPostProcessors a chance to return a proxy instead of the target bean instance.
//上面的的英文是官方解释:给一个创建一个代理对象bean的机会在bean的后置处理器中
//简单来说就是这里是提供给程序员实现的方法,比如你想代理一些bean,那么你就可以实现相关的后置处理器
//比如aop,或者你想为一些bean添加一些职责,那么只要返回不为空,spring就不会为你创建bean了,会直接用你创建的bean
//这个方法可以叫做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 {
//这个创建bean是spring容器自带的创建bean,也就是代码走到这里,则证明需要spring来创建bean了
//一般在spring项目中,普通的bean一般都会在这里由spring来创建,而特殊的Bean可能在上面由resolveBeforeInstantiation
//来直接创建了
Object beanInstance = doCreateBean(beanName, mbdToUse, args);
if (logger.isTraceEnabled()) {
logger.trace("Finished creating instance of bean '" + beanName + "'");
}
return beanInstance;
}
catch (BeanCreationException | ImplicitlyAppearedSingletonException ex) {
// A previously detected exception with proper bean creation context already,
// or illegal singleton state to be communicated up to DefaultSingletonBeanRegistry.
throw ex;
}
catch (Throwable ex) {
throw new BeanCreationException(
mbdToUse.getResourceDescription(), beanName, "Unexpected exception during bean creation", ex);
}
}
针对上面的方法,有些地方需要做一个demo来验证,也是对其的理解更加的深刻,我们研究creaeBean是根据实例化前、实例化、实例化后、填充属性、填充属性后、调用aware、初始化前、初始化、初始化后的顺序来讲解,我们先来看下实例化前,也就是上面的方法Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
实例化前方法调用
/**
* Apply before-instantiation post-processors, resolving whether there is a
* before-instantiation shortcut for the specified bean.
* @param beanName the name of the bean
* @param mbd the bean definition for the bean
* @return the shortcut-determined bean instance, or {@code null} if none
* 这个方法其实就是调用bean的后置处理器,bean的后置处理器有点多,分为
* 实例化前、实例化后、调用aware后、初始化前、初始化后
* 而下面这个方法就是在bean的实例化之前调用的,而这个方法是返回一个对象
* 所以如果说你这个方法调用完毕过后,返回的一个对象不为空,那么就说明你的bean已经存在了,已经有了
* 那么就不会在调用你后面的调用aware就是不会再调用spring提供的创建Bean的方法了
* 但是如果applyBeanPostProcessorsBeforeInstantiation返回的对象不为空,那么spring还猜想你可能还有
* 实例化的一些操作,所以这里还要调用那个实例化后的bean后置处理器applyBeanPostProcessorsAfterInitialization
* 按正常的逻辑,spring会通过实例化前、实例化后、调用aware后、初始化前、初始化后来调用后置处理器,但是下的这个方法
* 是你人为的干预了spring的实例化和初始化,那么你既然实例化了,那么就自己去调用初始化后的一些后置处理器,
* 请注意,这个方法也不会调用后面的aware方法了
*/
@Nullable
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) {
//applyBeanPostProcessorsBeforeInstantiation是调用的bean的实例化的后置处理器
bean = applyBeanPostProcessorsBeforeInstantiation(targetType, beanName);
if (bean != null) {
//如果返回的bean不为空,则证明spring不会去调用它自己的createBean方法了,因为你返回了对象
//所以下面还要看你有没有自己的bean初始化后的逻辑,如果有就调用,所以卫生么这个方法有
//bean的实例化前的方法和bean初始化后的方法
//applyBeanPostProcessorsAfterInitialization是调用的bean的初始化后置处理器
bean = applyBeanPostProcessorsAfterInitialization(bean, beanName);
}
}
}
mbd.beforeInstantiationResolved = (bean != null);
}
return bean;
}
看上面的代码逻辑,其实就是调用了初始化前,实例化后,如果调用了实例化前的方法已经返回了一个对象了,那么也就是说不用再调用spring后面的一些过程了,就直接是一个可用的对象了,也就是没有办法调用后面的实例化后,初始化以及aware等方法了,spring的设计就是这样的,但是为了使功能更加完善一点,如果调用实例化前的方法
applyBeanPostProcessorsBeforeInstantiation,如果这个时候返回一个不为空的对象,那么就意味着不用调用spring后面的方法,所以这个时候可以再调用自己实现的初始化后的后置处理方法applyBeanPostProcessorsAfterInitialization
实例化前
@Nullable
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;
}
看上面的过程可以知道获取了系统中的所有后置处理器,然后循环调用,如果这个后置处理器实现了InstantiationAwareBeanPostProcessor,那么调用实例化前的后置处理方法postProcessBeforeInstantiation
初始化后
/**
* 这个后置处理器的方法是bean初始化后的方法,请注意,这个方法要懂,否则可能你的初始化会出一些问题
* 这个方法的意思就是获取到系统中的所有bean后置处理器,如果调用任何一个处理器返回了null,那么就直接返回了
* 原有的对象,也就不会再去执行后续的@PostConstruct的方法了
* 这个方法的 意思就是每一个bean都要去调用下系统中存在的后置处理器,比如系统中有4个后置处理器,
* 如果其中一个后置处理器返回null,那么这个工序就不会走下去了,就会直接返回了
* @param existingBean the existing bean instance
* @param beanName the name of the bean, to be passed to it if necessary
* (only passed to {@link BeanPostProcessor BeanPostProcessors};
* can follow the {@link #ORIGINAL_INSTANCE_SUFFIX} convention in order to
* enforce the given instance to be returned, i.e. no proxies etc)
* @return
* @throws BeansException
*/
@Override
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;
}
这个后置处理器的方法是bean初始化后的方法,请注意,这个方法要懂,否则可能你的初始化会出一些问题, 这个方法的意思就是获取到系统中的所有bean后置处理器,如果调用任何一个处理器返回了null,那么就直接返回了原有的对象,也就不会再去执行后续的@PostConstruct的方法了
这个方法的 意思就是每一个bean都要去调用下系统中存在的后置处理器,比如系统中有4个后置处理器, 如果其中一个后置处理器返回null,那么这个工序就不会走下去了,就会直接返回了。
我们来写一个自己的bean后置处理器
@Component
public class Bml10BeanPostProcessor implements InstantiationAwareBeanPostProcessor {
@Override
public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
if(beanName.equals("orderService")){
System.out.println("OrderService 实例化前");
return new OrderService();
}
return null;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
if(beanName.equals("orderService")){
System.out.println("OrderService 初始化后");
}
return bean;
}
}
@Component
public class OrderService {
@PostConstruct
public void init(){
System.out.println("orderService init ...");
}
}
看上面的代码,我们的程序输出应该是
OrderService 实例化前
orderService init …
OrderService 初始化后
这个顺序才对,但是我们看输出的结果如下:
也就是说我们的初始化方法init没有执行,为什么呢?如果理解上面我在源码上写的注释就明白了,@PostConstruct是spring内置的初始化方法,也可以被叫做生命周期初始化回调方法,但是我们在执行Bml10BeanPostProcessor 后置处理器的时候,把orderService直接new出来返回了,那么这个时候就没有到后面的spring初始化前的后置方法,所以是不会执行的,@PostConstruct是在后置处理器
CommonAnnotationBeanPostProcessor中调用的,CommonAnnotationBeanPostProcessor继承了InitDestroyAnnotationBeanPostProcessor,所以执行初始化的@PostConstruct注解的方法是在InitDestroyAnnotationBeanPostProcessor中执行的,而上面的代码是在执行实例化就返回了一个对象了,则根本就不会走spring的下流程了,所以也就是为什么没有执行init方法,因为根本没有这块逻辑了,我们可以回忆看下上面的代码的实例化前返回对象的判断如下:
如果不为就直接返回了你实例化返回的对象,为了证明这块逻辑,我们修改下自己的后置处理器
@Override
public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
if(beanName.equals("orderService")){
System.out.println("OrderService 实例化前");
//return new OrderService();
}
return null;
}
我们返回一个空的对象
所以这个时候是去执行了后面的逻辑的;所以我们可认为resolveBeforeInstantiation这个方法是spring提供给程序员去扩展的,如果你的一个对象不想让spring来给你实例化和初始化,比如我们自己通过接口代理的一个对象就可以设置一个bean后置处理器,自己去创建一个代理对象出来,不用spring给我们实例化,场景很多,根据自己业务场景去使用。
doCreateBean
这个方法里面们包含了太多的bean生命周期的步骤,比如bean的实例化后、bean的实例化、bean的aware方法的调用、初始化、依赖注入,属性填充等步骤,这篇笔记主要记录下bean的实例化和初始化等一些后置处理器,所以其他先略过,后面会一一去记录所有的过程
protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
throws BeanCreationException {
// Instantiate the bean.
/**
* 下面的代码开始对bean实例化
*/
BeanWrapper instanceWrapper = null;
if (mbd.isSingleton()) {
instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
}
if (instanceWrapper == null) {
//bean的实例化,里面包含了推断构造方法,简单来说就是对bean进行实例化,这个方法后面来将
instanceWrapper = createBeanInstance(beanName, mbd, args);
}
Object bean = instanceWrapper.getWrappedInstance();
Class<?> beanType = instanceWrapper.getWrappedClass();
if (beanType != NullBean.class) {
mbd.resolvedTargetType = beanType;
}
// Allow post-processors to modify the merged bean definition.
synchronized (mbd.postProcessingLock) {
if (!mbd.postProcessed) {
try {
//spring提供的又一个bean后置处理器,就是在bean实例化完成过后,可以进行调用
//这个后置处理器可以传入指定的BeanDefinition,也就是你可以改变BeanDefinition的属性
//但是这个时候bean都已经实例化完成了,就算你修改了beanclass也没有用了
//但是有些属性我们还是可以设置的,比如可以手动设置初始化的方法mbd.setInitMethodName
//@AutoWired注解的切入点就是在这个后置处理器中找到的并且注入到缓存中
applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
}
catch (Throwable ex) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Post-processing of merged bean definition failed", ex);
}
mbd.postProcessed = true;
}
}
// Eagerly cache singletons to be able to resolve circular references
// even when triggered by lifecycle interfaces like BeanFactoryAware.
boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
isSingletonCurrentlyInCreation(beanName));
if (earlySingletonExposure) {
if (logger.isTraceEnabled()) {
logger.trace("Eagerly caching bean '" + beanName +
"' to allow for resolving potential circular references");
}
//和循环依赖有关,后面讲
addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
}
// Initialize the bean instance.
Object exposedObject = bean;
try {
/**
* 填充属性,处理@AutoWried,调用bean的实例化后的方法
*/
populateBean(beanName, mbd, instanceWrapper);
/**
* 这个方法是调用bean的初始化方法的
*/
exposedObject = initializeBean(beanName, exposedObject, mbd);
}
catch (Throwable ex) {
if (ex instanceof BeanCreationException && beanName.equals(((BeanCreationException) ex).getBeanName())) {
throw (BeanCreationException) ex;
}
else {
throw new BeanCreationException(
mbd.getResourceDescription(), beanName, "Initialization of bean failed", ex);
}
}
//下面是依赖注入的代码,这个后面说
if (earlySingletonExposure) {
Object earlySingletonReference = getSingleton(beanName, false);
if (earlySingletonReference != null) {
if (exposedObject == bean) {
exposedObject = earlySingletonReference;
}
else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) {
String[] dependentBeans = getDependentBeans(beanName);
Set<String> actualDependentBeans = new LinkedHashSet<>(dependentBeans.length);
for (String dependentBean : dependentBeans) {
if (!removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) {
actualDependentBeans.add(dependentBean);
}
}
if (!actualDependentBeans.isEmpty()) {
throw new BeanCurrentlyInCreationException(beanName,
"Bean with name '" + beanName + "' has been injected into other beans [" +
StringUtils.collectionToCommaDelimitedString(actualDependentBeans) +
"] in its raw version as part of a circular reference, but has eventually been " +
"wrapped. This means that said other beans do not use the final version of the " +
"bean. This is often the result of over-eager type matching - consider using " +
"'getBeanNamesForType' with the 'allowEagerInit' flag turned off, for example.");
}
}
}
}
// Register bean as disposable.
try {
registerDisposableBeanIfNecessary(beanName, bean, mbd);
}
catch (BeanDefinitionValidationException ex) {
throw new BeanCreationException(
mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex);
}
return exposedObject;
}
applyMergedBeanDefinitionPostProcessors
/**
* Apply MergedBeanDefinitionPostProcessors to the specified bean definition,
* invoking their {@code postProcessMergedBeanDefinition} methods.
* @param mbd the merged bean definition for the bean
* @param beanType the actual type of the managed bean instance
* @param beanName the name of the bean
* @see MergedBeanDefinitionPostProcessor#postProcessMergedBeanDefinition
* 这个方法我个人的理解是可以被叫做合并bean过后的bean后置处理器
* @AutoWired注解和@Value以及@Inject注解都是在这个后置处理器中实现的
* 具体的后置处理器是AutowiredAnnotationBeanPostProcessor,在里面调用了postProcessMergedBeanDefinition
*/
protected void applyMergedBeanDefinitionPostProcessors(RootBeanDefinition mbd, Class<?> beanType, String beanName) {
for (BeanPostProcessor bp : getBeanPostProcessors()) {
if (bp instanceof MergedBeanDefinitionPostProcessor) {
MergedBeanDefinitionPostProcessor bdp = (MergedBeanDefinitionPostProcessor) bp;
bdp.postProcessMergedBeanDefinition(mbd, beanType, beanName);
}
}
}
这个bean的后置处理器是在spring实例化之前方法调用过后,bean开始实例化,bean实例化后过后调用的一个合并bean的后置处理,请注意,这个不是bean的实例化后的后置处理器,所有代码到这里的调用顺序是:bean实例化前后置处理->bean实例化->合并bean后置处理->bean实例化后后置处理
但是这个后置处理我们注意看它的参数就知道,它不是把你实例化得到的bean对象传入的,而是传入的RootBeanDefinition,那么我们想一下这个时候如果你传入的是BeanDefinition,那么你修改了BeanDefinition,还起作用吗?实际上这个时候bean以及实例化了,你修改了beanclass也没有用,但是总有业务场景可以使用到,就是你可以介入spring的实例化后过程,想加自己的业务逻辑,但是这里我们可以想到的是它本身可以在BeanDefinition中设置初始化方法,也就是initMethod,比如看下面的例子
@Component
public class Bml10MergedBeanDefinitionPostProcessor implements MergedBeanDefinitionPostProcessor {
@Override
public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName) {
if(beanName.equals("orderService")){
beanDefinition.setInitMethodName("margedInit");
}
}
}
@Component
public class OrderService {
@PostConstruct
public void init(){
System.out.println("orderService init ...");
}
public void margedInit(){
System.out.println("margedInit init ...");
}
}
OrderService中的两个初始化方法都已经调用了,一个是通过注解@PostConstruct来实现的,一个是我们通过后置处理器MergedBeanDefinitionPostProcessor 来添加的,添加的位置是在bean的实例化之后添加的,那么总有一个地方去调用,我们先记着这个点,下面会讲解在哪里调用的,而且是在@PostConstruct之后调用的
填充属性&实例化后(populateBean)
/**
* Populate the bean instance in the given BeanWrapper with the property values
* from the bean definition.
* @param beanName the name of the bean
* @param mbd the bean definition for the bean
* @param bw the BeanWrapper with bean instance
* 这个方法是填充属性的方法,但是在这个方法里面调用了Bean的后置处理器实例化后,因为实例化前在前面调用,这里调用的是
* 实例化后
*/
@SuppressWarnings("deprecation") // for postProcessPropertyValues
protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) {
if (bw == null) {
if (mbd.hasPropertyValues()) {
throw new BeanCreationException(
mbd.getResourceDescription(), beanName, "Cannot apply property values to null instance");
}
else {
// Skip property population phase for null instance.
return;
}
}
// Give any InstantiationAwareBeanPostProcessors the opportunity to modify the
// state of the bean before properties are set. This can be used, for example,
// to support styles of field injection.
//这里是调用实例化后的后置处理器
if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
for (BeanPostProcessor bp : getBeanPostProcessors()) {
if (bp instanceof InstantiationAwareBeanPostProcessor) {
InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
if (!ibp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {
return;
}
}
}
}
/**
* 下面的这段逻辑处理的是@AutoWired,后面在说
*/
PropertyValues pvs = (mbd.hasPropertyValues() ? mbd.getPropertyValues() : null);
int resolvedAutowireMode = mbd.getResolvedAutowireMode();
if (resolvedAutowireMode == AUTOWIRE_BY_NAME || resolvedAutowireMode == AUTOWIRE_BY_TYPE) {
MutablePropertyValues newPvs = new MutablePropertyValues(pvs);
// Add property values based on autowire by name if applicable.
if (resolvedAutowireMode == AUTOWIRE_BY_NAME) {
autowireByName(beanName, mbd, bw, newPvs);
}
// Add property values based on autowire by type if applicable.
if (resolvedAutowireMode == AUTOWIRE_BY_TYPE) {
autowireByType(beanName, mbd, bw, newPvs);
}
pvs = newPvs;
}
boolean hasInstAwareBpps = hasInstantiationAwareBeanPostProcessors();
boolean needsDepCheck = (mbd.getDependencyCheck() != AbstractBeanDefinition.DEPENDENCY_CHECK_NONE);
PropertyDescriptor[] filteredPds = null;
if (hasInstAwareBpps) {
if (pvs == null) {
pvs = mbd.getPropertyValues();
}
/**
* 这里调用的又是bean的后置处理器,这里的后置处理器是在bean属性填充过后的bean后置处理器
* 这个后置处理器正在现在用的最多,spring内部定义的InstantiationAwareBeanPostProcessor实现了这个接口,主要处理的是
* @AutoWired的后置处理器,依赖注入的在这里调用的,最重要的是postProcessProperties这个方法
* 所以InstantiationAwareBeanPostProcessor的后置处理器方法postProcessProperties是处理@AutoWired @Resource注解的
* 这个方法后面讲
*/
for (BeanPostProcessor bp : getBeanPostProcessors()) {
if (bp instanceof InstantiationAwareBeanPostProcessor) {
InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
PropertyValues pvsToUse = ibp.postProcessProperties(pvs, bw.getWrappedInstance(), beanName);
if (pvsToUse == null) {
if (filteredPds == null) {
filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
}
pvsToUse = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);
if (pvsToUse == null) {
return;
}
}
pvs = pvsToUse;
}
}
}
if (needsDepCheck) {
if (filteredPds == null) {
filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
}
checkDependencies(beanName, mbd, filteredPds, pvs);
}
if (pvs != null) {
applyPropertyValues(beanName, mbd, bw, pvs);
}
}
这个方法的
代码片段就是调用了实例化之后的后置处理器,我们修改下之前的后置处理器,在Bml10BeanPostProcessor中实现一个实例化后的后置处理方法
@Override
public boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {
if(beanName.equals("orderService")){
System.out.println("OrderService 实例化后");
}
return true;
}
请注意,这个方法是返回了一个booelan的所以如果返回false的话,那么这个方法的后面的逻辑就不会执行了,也就是你的bean里面的比如你试下了ApplicationContextAware,那么后面的就不会执行了,比如:
@Override
public boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {
if(beanName.equals("orderService")){
System.out.println("OrderService 实例化后");
}
return false;
}
@Component
public class OrderService {
@Autowired
private UserService userService;
@PostConstruct
public void init(){
System.out.println("orderService init ...");
}
public void margedInit(){
System.out.println("margedInit init ...");
}
public void tests(){
System.out.println("userService="+userService);
}
}
所以如果你在实例化后的后置处理器中如果返回了false,那么你的这个bean的所有属性填充,依赖注入都是失效的,所以要多注意使用方法
@AutoWired的实现逻辑&属性填充后的后置处理器
@AutoWired中的逻辑也是在InstantiationAwareBeanPostProcessor这个后置处理器中实现的,当然了你也可以实现这个后置处理器,但是spring内部有自己的后置处理器专门来处理依赖注入的逻辑的后置处理器,具体的后置处理器是
CommonAnnotationBeanPostProcessor,这个后面记录依赖注入的时候再来讲。
初始化Bean
exposedObject = initializeBean(beanName, exposedObject, mbd)这段逻辑就是初始化bean的,这个方法里面包含了spring内置的aware方法的调用,初始化前方法的调用、初始化后的方法调用,BeanDefinition中的初始化方法的调用,程序员实现了Aware方法的调用等
initializeBean
/**
* Initialize the given bean instance, applying factory callbacks
* as well as init methods and bean post processors.
* <p>Called from {@link #createBean} for traditionally defined beans,
* and from {@link #initializeBean} for existing bean instances.
* @param beanName the bean name in the factory (for debugging purposes)
* @param bean the new bean instance we may need to initialize
* @param mbd the bean definition that the bean was created with
* (can also be {@code null}, if given an existing bean instance)
* @return the initialized bean instance (potentially wrapped)
* @see BeanNameAware
* @see BeanClassLoaderAware
* @see BeanFactoryAware
* @see #applyBeanPostProcessorsBeforeInitialization
* @see #invokeInitMethods
* @see #applyBeanPostProcessorsAfterInitialization
*
* 调用顺序是先
* 1.调用spring内部的aware方法
* 2.bean的初始化前的后置处理器
* 3.bean的初始化方法调用
* 4.bean的初始化后的方法调用
*/
protected Object initializeBean(String beanName, Object bean, @Nullable RootBeanDefinition mbd) {
if (System.getSecurityManager() != null) {
AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
invokeAwareMethods(beanName, bean);
return null;
}, getAccessControlContext());
}
else {
//调用默认的aware方法
invokeAwareMethods(beanName, bean);
}
Object wrappedBean = bean;
if (mbd == null || !mbd.isSynthetic()) {
//初始化前后置处理器
wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
}
try {
//调用初始化方法,InitializingBean中的初始化方法或者BeanDefinition中设置的初始化方法
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;
}
private void invokeAwareMethods(String beanName, Object bean) {
if (bean instanceof Aware) {
if (bean instanceof BeanNameAware) {
((BeanNameAware) bean).setBeanName(beanName);
}
if (bean instanceof BeanClassLoaderAware) {
ClassLoader bcl = getBeanClassLoader();
if (bcl != null) {
((BeanClassLoaderAware) bean).setBeanClassLoader(bcl);
}
}
if (bean instanceof BeanFactoryAware) {
((BeanFactoryAware) bean).setBeanFactory(AbstractAutowireCapableBeanFactory.this);
}
}
}
调用spring内置的aware,分了三类:
1.如果你的bean实现了BeanNameAware,那么就会当前的beanName回调给你;
2.如果你的bean实现了BeanClassLoaderAware,那么spring会把当前的spring类加载器回调给你;
3.如果你实现了BeanFactoryAware,那么spring会把bean工厂回调给你。
上面的aware是spring内置的aware,我感觉都非常有用,特别是bean工厂这个功能特别强大,简单来说就是有了工厂bean,我们能干很多事儿。但是不知道看客的你是否有注意到,我们平时使用的一个aware,ApplicationContextAware在这里没有呢?ApplicationContextAware这个aware更强大,可以得到spring的上下文,也就是拥有了所有,但是我们一般获取整个是用来获取bean比较多一点,就是在一些没有加入容器的类中可以通过一个容器中bean实现了ApplicationContextAware来获取bean,但是这个bean在哪里实现的呢?在bean初始化的后置处理器调用的,下面会说。
初始化前后置处理器
wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
public Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName)
throws BeansException {
/**
* 这个方法是调用spring的初始化前的后置处理器,请注意这里的代码逻辑
* 比如这里有4个后置处理器,你自己写的类实现了这个后置处理器,不要反返回null
* 因为bean对象已经给你了,如果你返回了null,那么则后面的后置处理器都不会执行了,看
* if条件可知,你局当成这是一个工序,每一个工序都依赖于前一个工序,如果前一个工序告诉你没有货物了,
* 那么下面的工序也没有办法走了,这个和初始前的后置处理器处理的方案是一模一样的
*
*/
Object result = existingBean;
for (BeanPostProcessor processor : getBeanPostProcessors()) {
Object current = processor.postProcessBeforeInitialization(result, beanName);
if (current == null) {
return result;
}
result = current;
}
return result;
}
初始化前的后置处理器,这个处理器有意思的,就是系统中的后置处理器,但凡任何一个后置处理器返回了null,那么就直接返回原bean对象,后面的后置处理器就不会执行了
@PostConstruct就是在这个后置处理器中调用的;而ApplicationContextAware也是在这个后置处理器中调用的,也就是初始化前的后置处理器,这个后置处理器中有两个spring内置的处理器:
InitDestroyAnnotationBeanPostProcessor:处理@PostConcustruct
ApplicationContextAwareProcessor:处理程序员自定义的Aware,比如ApplicationContextAware,还有很多,比如下面的截图:
所以初始化前我们知道spring会调用
1.程序员实现了Aware接口
2.@PostConstruct初始化方法
3.程序员实现的postProcessBeforeInitialization后置处理器方法
初始化方法
invokeInitMethods(beanName, wrappedBean, mbd);
这个方法全部是初始化方法的调用,分为:
1.实现了InitializingBean的方法调用afterPropertiesSet()方法;
2.BeanDefinition中设置的initMethod方法,也是初始化方法
/**
* Give a bean a chance to react now all its properties are set,
* and a chance to know about its owning bean factory (this object).
* This means checking whether the bean implements InitializingBean or defines
* a custom init method, and invoking the necessary callback(s) if it does.
* @param beanName the bean name in the factory (for debugging purposes)
* @param bean the new bean instance we may need to initialize
* @param mbd the merged bean definition that the bean was created with
* (can also be {@code null}, if given an existing bean instance)
* @throws Throwable if thrown by init methods or by the invocation process
* @see #invokeCustomInitMethod
* 这个是spring的初始化方法,其实就是调用bean的初始化方法,这个方法的初始化方法有两个地方,第一个是实现了InitializingBean的初始化方法
* 第二个是在BeanDefinition中设置了initMethod方法,而已可以在这里调用
*/
protected void invokeInitMethods(String beanName, 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类中的初始化的方法
((InitializingBean) bean).afterPropertiesSet();
}
}
/**
* 下面是调用BeanDefinition中设置的initMethod方法,也是初始化方法
*/
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);
}
}
}
这个初始化方法简单,这里就不说了,我们最上面说的实现了MergedBeanDefinitionPostProcessor 的用BeanDefinition设置了一个initMethod在哪里调用的,其实就是在这里调用的。
初始化后后置处理器
wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName)这个是spring bean生命周期的最后一步了,就是bean初始化完成了,最后执行生命周期初始化后的后置处理器,这个方法在实例化前返回了不为空的bean对象已经说过了。这里就不说了,spring的这个声明周期的太多后置处理器,说实话,有点绕,不看到代码还有点记不清详细的顺序步骤,所以,我这里准备画一个图来把流程理清楚。
本文地址:https://blog.csdn.net/scjava/article/details/109271899
上一篇: ssm框架整合演示
下一篇: 监控关闭窗口,点击确定执行事件