Spring中Bean创建过程之源码分析

一、概述

在Spring进行完IoC容器的初始化之后,IoC容器中就拥有了管理Bean的所有信息,在调用BeanFactory的getBean()方法时,或有其他Bean实例依赖时,就会创建出实例来,本文主要分析Bean的生命周期,其生命周期包括:实例化-->属性赋值-->初始化-->销毁

1. 实例化: 在Bean实例被调用或被依赖的实例被创建,该Bean实例会被创建,利用该类的构造方法来实例化该类。

2. 属性赋值: 当该Bean的属性依赖其他对象时候,比如属性中有被@Autowired注解的属性,会将其他对象的引用赋予给他。

3. 初始化: 初始化主要用以进行一些预处理和后处理。

  • Bean创建前后处理器:主要包括BeanPostProcessor一系列方法,在容器启动的时候就调用的方法;
  • Aware类接口实现:主要是通过Aware类的方法,比如BeanNameAware方法等,它能够拿到BeanName等资源,该级别方法是在初始化之前完成;
  • Bean中具体方法:主要通过重写InitializingBean接口中的一些方法来是吸纳,包括初始化和销毁这两个方法;

4. 销毁: 当容器被关闭时该Bean会被销毁,销毁前的操作看其时候有定义。

二、创建过程中的常见类

1.BeanFactory和FactoryBean的区别

BeanFactory是生产Bean的工厂类,其工作流程主要包括:定位 -->加载-->注册。

Spring中的Bean可以根据默认你的BeanFactory来生成Bean实例,对于特殊的Bean也可以自定义工厂类来实现,这就可以通过实现FactoryBean接口来实现,其接口的主要方法为:

  • T getObject():根据该工厂类生产的bean实例。
  • Class<?> getObjectType():根据该工厂类生产的实例Class类型。

以下举例说明FactoryBean接口的使用:

java 复制代码
//spring-config.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:P="http://www.springframework.org/schema/p"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

    <bean id="car" class="com.yangnk.test2.CarFactoryBean" P:carInfo="大奔,600,1000000"/>

</beans>
      

---
      
//Car.java

public class Car {
    private int maxSpeed ;
    private String brand ;
    private double price ;
  
---
//CarFactoryBean.java
public class CarFactoryBean implements FactoryBean<Car> {
    private String carInfo ;

    public String getCarInfo(){
        return  this.carInfo;
    }
    
    public void setCarInfo (String carInfo){
        this.carInfo = carInfo;
    }

    @Override
    public Car getObject() throws Exception {
        Car car = new  Car();
        String[] infos = carInfo.split(",");
        car.setBrand(infos[0]);
        car.setMaxSpeed(Integer.valueOf(infos[1]));
        car.setPrice(Double.valueOf(infos[2]));
        return  car;
    }

    @Override
    public Class<?> getObjectType() {
        return Car.class;
    }

    @Override
    public boolean isSingleton() {
        return true;
    }
  
---
//SpringTest1.java
  public class SpringTest1 {
    public static void main(String[] args) {
        BeanFactory bf = new XmlBeanFactory( new ClassPathResource("spring-config.xml"));
        Car car = (Car) bf.getBean("car");
        System.out.println("car.toString() = " + car.toString());
    }
}
  

最后执行的结果为:

2.BeanWrapper

就是Bean的一个包装类,是在属性赋值之后产生的。

三、解决循环依赖

Spring通过三级缓存和提前暴露的思路来解决循环依赖。主要思路是将循环依赖的对象实例放到缓存中,让对方先实例化再进行初始化。三级缓存包括:SingletonObjects、EarlySingletonObjects、SingletonFactories。

1. SingletonObjects: 已经实例化和初始化的bean放到该map中;用于保存beanName和bean实例之间的关系。

2. EarlySingletonObjects: 已经实例化,但是没有初始化的bean放到该map中;也是用以保存beanName和bean实例之间的关系,和SingletonObjects区别是他是通过SingletonFactories生成的,为解决循环依赖,而没有进行初始化的bean。

3. SingletonFactories: 创建bean的factory放到该map中;用以保存beanName和BeanFactory类之间观念的。

如果对象A和对象B相互循环依赖,会通过以下步骤解决:

  1. 对象A实例化前会去查询SingletonObjects,如果没有,将其工厂类后放置到SingletonFactories中,再进行下一步属性赋值,由于依赖对象B,所以需要对象B实例化;
  2. 对象B实例化前会去查询SingletonObjects和EarlySingletonObjects,如果没有,将其工厂类后放置到SingletonFactories中,再进行下一步属性赋值,由于依赖对象A,会去查询SingletonFactories,同个getObject()方产生的bean添加到二级缓存EarlySingletonObjects中,同时对象B实例化成功;
  3. 对象A在EarlySingletonObjects了,继续进行属性赋值,能够正常属性赋值对象B;
  4. 依赖注入成功后会将SingletonFactories和EarlySingletonObjects中的对象删除。

具体的代码实现可以后续源码分析。

四、源码层面分析Bean的创建过程

从getBean()方法开始分析:

java 复制代码
public static void main(String[] args) {
   // 创建一个Spring容器
   ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring.xml");
   User user1 = (User) applicationContext.getBean("user1");
   user1.sayHello();
}

1.实例化阶段

开始创建bean实例,会首先判断是否能从缓存中取值,如果没有的话才会自己创建。在创建过程中会根据类型分为singleton还是prototype区别创建。

java 复制代码
//AbstractBeanFactory.java

protected <T> T doGetBean(
      String name, @Nullable Class<T> requiredType, @Nullable Object[] args, boolean typeCheckOnly)
      throws BeansException {

   // name有可能是 &xxx 或者 xxx,如果name是&xxx,那么beanName就是xxx
   // name有可能传入进来的是别名,那么beanName就是id
   String beanName = transformedBeanName(name);
   Object beanInstance;
  	
  ...
    

// Create bean instance.
//my-开始创建bean实例,分为singleton还是prototype
if (mbd.isSingleton()) {
  sharedInstance = getSingleton(beanName, () -> {
    try {
      return createBean(beanName, mbd, args);
    }
    catch (BeansException ex) {
      // Explicitly remove instance from singleton cache: It might have been put there
      // eagerly by the creation process, to allow for circular reference resolution.
      // Also remove any beans that received a temporary reference to the bean.
      destroySingleton(beanName);
      throw ex;
    }
  });
  beanInstance = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
}

这一段是解决循环依赖的核心逻辑,其主要逻辑是:先从singletonObject中后去bean,如果获取不到再从earlySingletonObjects中获取,如果都获取不到,则从singletonFactories获取bean对象的ObjectFactory,该类是创建该bean的工厂类,再将该工厂类创建的singletonObject放到earlySingletonObjects中,并且同时创建singletonFactories中的bean。

java 复制代码
//DefaultSingletonBeanRegistry

protected Object getSingleton(String beanName, boolean allowEarlyReference) {
   // Quick check for existing instance without full singleton lock
   Object singletonObject = this.singletonObjects.get(beanName);
   if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
      singletonObject = this.earlySingletonObjects.get(beanName);
      if (singletonObject == null && allowEarlyReference) {
         synchronized (this.singletonObjects) {
            // Consistent creation of early reference within full singleton lock
            singletonObject = this.singletonObjects.get(beanName);
            if (singletonObject == null) {
               singletonObject = this.earlySingletonObjects.get(beanName);
               if (singletonObject == null) {
                  ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
                  if (singletonFactory != null) {
                     singletonObject = singletonFactory.getObject();
                     this.earlySingletonObjects.put(beanName, singletonObject);
                     this.singletonFactories.remove(beanName);
                  }
               }
            }
         }
      }
   }
   return singletonObject;
}

开始进行实例化,其中resolveBeforeInstantiation(beanName, mbdToUse)是实现AOP的关键,如果该类需要实现AOP代理,通过该方法会返回其代理类。

java 复制代码
//AbstractAutowireCapableBeanFactory.java

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;

   // 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.
   // 马上就要实例化Bean了,确保beanClass被加载了
   Class<?> resolvedClass = resolveBeanClass(mbd, beanName);
   if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) {
      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.
      // 实例化前
      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 {
      Object beanInstance = doCreateBean(beanName, mbdToUse, args);
      if (logger.isTraceEnabled()) {
         logger.trace("Finished creating instance of bean '" + beanName + "'");
      }
      return beanInstance;
   }
  
  
---
protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
      throws BeanCreationException {

   // 实例化bean
   // Instantiate the bean.
   BeanWrapper instanceWrapper = null;
   if (mbd.isSingleton()) {
      // 有可能在本Bean创建之前,就有其他Bean把当前Bean给创建出来了(比如依赖注入过程中)
      instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
   }
   if (instanceWrapper == null) {
      // 创建Bean实例
      instanceWrapper = createBeanInstance(beanName, mbd, args);
   }
   Object bean = instanceWrapper.getWrappedInstance();
   Class<?> beanType = instanceWrapper.getWrappedClass();
   if (beanType != NullBean.class) {
      mbd.resolvedTargetType = beanType;
   }

   // 后置处理合并后的BeanDefinition
   // Allow post-processors to modify the merged bean definition.
   synchronized (mbd.postProcessingLock) {
      if (!mbd.postProcessed) {
         try {
            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 {
      // 属性填充
      populateBean(beanName, mbd, instanceWrapper);

      // 初始化
      exposedObject = initializeBean(beanName, exposedObject, mbd);
     ...

实例化阶段的核心流程,如果有指定构造方法就用指定构造方法,如果没有则用默认构造方法instantiateBean(beanName, mbd),这些生成的结果都保存在BeanWrapper中。

java 复制代码
//AbstractAutowireCapableBeanFactory.java

protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) {
   // Make sure bean class is actually resolved at this point.
   Class<?> beanClass = resolveBeanClass(mbd, beanName);

   if (beanClass != null && !Modifier.isPublic(beanClass.getModifiers()) && !mbd.isNonPublicAccessAllowed()) {
      throw new BeanCreationException(mbd.getResourceDescription(), beanName,
            "Bean class isn't public, and non-public access not allowed: " + beanClass.getName());
   }

   // BeanDefinition中添加了Supplier,则调用Supplier来得到对象
   Supplier<?> instanceSupplier = mbd.getInstanceSupplier();
   if (instanceSupplier != null) {
      return obtainFromSupplier(instanceSupplier, beanName);
   }

   // @Bean对应的BeanDefinition
   if (mbd.getFactoryMethodName() != null) {
      return instantiateUsingFactoryMethod(beanName, mbd, args);
   }

   // Shortcut when re-creating the same bean...
   // 一个原型BeanDefinition,会多次来创建Bean,那么就可以把该BeanDefinition所要使用的构造方法缓存起来,避免每次都进行构造方法推断
   boolean resolved = false;
   boolean autowireNecessary = false;
   if (args == null) {
      synchronized (mbd.constructorArgumentLock) {
         if (mbd.resolvedConstructorOrFactoryMethod != null) {
            resolved = true;
            // autowireNecessary表示有没有必要要进行注入,比如当前BeanDefinition用的是无参构造方法,那么autowireNecessary为false,否则为true,表示需要给构造方法参数注入值
            autowireNecessary = mbd.constructorArgumentsResolved;
         }
      }
   }
   if (resolved) {
      // 如果确定了当前BeanDefinition的构造方法,那么看是否需要进行对构造方法进行参数的依赖注入(构造方法注入)
      if (autowireNecessary) {
         // 方法内会拿到缓存好的构造方法的入参
         return autowireConstructor(beanName, mbd, null, null);
      }
      else {
         // 构造方法已经找到了,但是没有参数,那就表示是无参,直接进行实例化
         return instantiateBean(beanName, mbd);
      }
   }

   // 如果没有找过构造方法,那么就开始找了

   // Candidate constructors for autowiring?
   // 提供一个扩展点,可以利用SmartInstantiationAwareBeanPostProcessor来控制用beanClass中的哪些构造方法
   // 比如AutowiredAnnotationBeanPostProcessor会把加了@Autowired注解的构造方法找出来,具体看代码实现会更复杂一点
   Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);

   // 如果推断出来了构造方法,则需要给构造方法赋值,也就是给构造方法参数赋值,也就是构造方法注入
   // 如果没有推断出来构造方法,但是autowiremode为AUTOWIRE_CONSTRUCTOR,则也可能需要给构造方法赋值,因为不确定是用无参的还是有参的构造方法
   // 如果通过BeanDefinition指定了构造方法参数值,那肯定就是要进行构造方法注入了
   // 如果调用getBean的时候传入了构造方法参数值,那肯定就是要进行构造方法注入了
   if (ctors != null || mbd.getResolvedAutowireMode() == AUTOWIRE_CONSTRUCTOR ||
         mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args)) {
      return autowireConstructor(beanName, mbd, ctors, args);
   }

   // Preferred constructors for default construction?
   ctors = mbd.getPreferredConstructors();
   if (ctors != null) {
      return autowireConstructor(beanName, mbd, ctors, null);
   }

   // No special handling: simply use no-arg constructor.
   // 不匹配以上情况,则直接使用无参构造方法
   return instantiateBean(beanName, mbd);
}

2.属性赋值阶段

开始进行属性赋值,核心方法是populateBean(),其是将BeanDefinition中的属性设置为PropertyValues对象,再把结果保存到BeanWrapper中。

java 复制代码
	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 (InstantiationAwareBeanPostProcessor bp : getBeanPostProcessorCache().instantiationAware) {
				if (!bp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {
					return;
				}
			}
		}

		PropertyValues pvs = (mbd.hasPropertyValues() ? mbd.getPropertyValues() : null);

		int resolvedAutowireMode = mbd.getResolvedAutowireMode();
		if (resolvedAutowireMode == AUTOWIRE_BY_NAME || resolvedAutowireMode == AUTOWIRE_BY_TYPE) {
			// MutablePropertyValues是PropertyValues具体的实现类
			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();
			}
			for (InstantiationAwareBeanPostProcessor bp : getBeanPostProcessorCache().instantiationAware) {
				// 这里会调用AutowiredAnnotationBeanPostProcessor的postProcessProperties()方法,会直接给对象中的属性赋值
				// AutowiredAnnotationBeanPostProcessor内部并不会处理pvs,直接返回了
				PropertyValues pvsToUse = bp.postProcessProperties(pvs, bw.getWrappedInstance(), beanName);
				if (pvsToUse == null) {
					if (filteredPds == null) {
						filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
					}
					pvsToUse = bp.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);
		}

		// 如果当前Bean中的BeanDefinition中设置了PropertyValues,那么最终将是PropertyValues中的值,覆盖@Autowired
		if (pvs != null) {
			applyPropertyValues(beanName, mbd, bw, pvs);
		}
	}

3.初始化阶段

开始进行初始化,主要是通过initializeBean()来实现的,在这个方法中,会实现几个拓展点,包括激活 Aware 方法,实现后置处理器BeanPostProcessors,激活自定义方法invokeInitMethods()。

java 复制代码
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 {
      invokeAwareMethods(beanName, bean);
   }

   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);
   }

   // 初始化后 AOP
   if (mbd == null || !mbd.isSynthetic()) {
      wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
   }

4.销毁阶段

五、创建过程中Bean的扩展点

针对于创建Bean过程中可用的Bean扩展点方式,我做了一下总结:

Aware类接口

  • BeanFactoryAware/ApplicationContextAware:会获取BeanFactory、ApplicationContext,可以对其操作;
  • BeanNameAware:会获取BeanName,可以对其操作;

针对Bean的前置后置处理器

  • BeanPostProcessor:每次实例化Bean后都会调用该接口;
  • InitializingBean:初始化前会调用该接口;
  • DisposableBean:销毁后会调用该接口;

针对Bean中的方法前置后置处理

  • @PostConstruct:构造方法执行完后会执行该方法
  • @PreDestroy:销毁前会执行该方法;

六、总结

TODO

  • 详细说明BeanWrapper。
  • 绘制时序图。

参考资料

  1. spring5 源码深度解析----- IOC 之 bean 的初始化:www.cnblogs.com/java-chen-h...
相关推荐
Easonmax2 小时前
用 Rust 打造可复现的 ASCII 艺术渲染器:从像素到字符的完整工程实践
开发语言·后端·rust
百锦再2 小时前
选择Rust的理由:从内存管理到抛弃抽象
android·java·开发语言·后端·python·rust·go
小羊失眠啦.2 小时前
深入解析Rust的所有权系统:告别空指针和数据竞争
开发语言·后端·rust
q***71852 小时前
Spring Boot 集成 MyBatis 全面讲解
spring boot·后端·mybatis
大象席地抽烟2 小时前
使用 Ollama 本地模型与 Spring AI Alibaba
后端
程序员小假2 小时前
SQL 语句左连接右连接内连接如何使用,区别是什么?
java·后端
小坏讲微服务3 小时前
Spring Cloud Alibaba Gateway 集成 Redis 限流的完整配置
数据库·redis·分布式·后端·spring cloud·架构·gateway
方圆想当图灵3 小时前
Nacos 源码深度畅游:Nacos 配置同步详解(下)
分布式·后端·github
方圆想当图灵3 小时前
Nacos 源码深度畅游:Nacos 配置同步详解(上)
分布式·后端·github
小羊失眠啦.4 小时前
用 Rust 实现高性能并发下载器:从原理到实战
开发语言·后端·rust