Java Spring

1、什么是循环依赖?

2021-05-18-09-33-07-223398.png
循环依赖就是循环引用,就是两个或多个bean相互之间的持有对方。A类中有一个B类型的成员变量,需要注入BB类中有一个A类型的成员变量,需要注入A

2、循环依赖的场景

2.1、构造器的循环依赖【Spring无法解决】

两个循环依赖的类

  1. //A类
  2. public Class A{
  3. private B b;
  4. pubcli A(B b){
  5. this.b=b;
  6. }
  7. }
  8. //B类
  9. public Class B{
  10. private A a;
  11. public B(A a){
  12. this. a=a;
  13. }
  14. }

xml配置信息为

  1. <bean id="a" class="com.make.spring.A">
  2. <constructor-arg name="b" ref="b"></constructor-arg>
  3. </bean>
  4. <bean id="b" class="com.make.spring.B">
  5. <constructor-arg name="a" ref="a"></constructor-arg>
  6. </bean>

主方法的内容如下

  1. public static void main(String[] args) {
  2. ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("springConstructor.xml");
  3. A bean = context.getBean(A.class);
  4. System.out.println(bean);
  5. }

启动报错信息如下:
2021-05-18-09-33-07-305196.png
Spring是无法解决构造函数循环依赖注入的,因为这种时候,在实例化A的时候就要获取B的实例化对象,在实例化B的时候要A的实例化对象,所以无法创建任何一个实例。

2.2、setter方法注入属性,singleton单例模式

  1. public class A {
  2. private B b;
  3. public void setB(B b) {
  4. this.b = b;
  5. }
  6. public B getB() {
  7. return b;
  8. }
  9. }
  10. public class B {
  11. private A a;
  12. public void setA(A a) {
  13. this.a = a;
  14. }
  15. public A getA() {
  16. return a;
  17. }
  18. }

xml配置信息

  1. <bean id="a" class="com.make.bean.A">
  2. <property name="b" ref="b"></property>
  3. </bean>
  4. <bean id="b" class="com.make.bean.B">
  5. <property name="a" ref="a"></property>
  6. </bean>

主方法信息

  1. public static void main(String[] args) {
  2. ClassPathXmlApplicationContext context=new ClassPathXmlApplicationContext("spring.xml");
  3. A beanA =context.getBean(A.class);
  4. System.out.println(beanA.getB());
  5. B beanB=context.getBean(B.class);
  6. System.out.println(beanB.getA());
  7. }

最后成功的打印信息
2021-05-18-09-33-07-394942.png
这种情况下,Spring将A的对象实例化后,还未注入属性的A提前缓存起来,也就是提前暴露A,然后让B的实例化过程拿到A来解决依赖注入。

2.3、setter方式,prototype原型模式【Spirng无法解决】

两个java类的内容和主方法的内容和1.2的相同
xml配置信息

  1. <bean id="a" class="com.make.bean.A" scope="prototype">
  2. <property name="b" ref="b"></property>
  3. </bean>
  4. <bean id="b" class="com.make.bean.B" scope="prototype">
  5. <property name="a" ref="a"></property>
  6. </bean>

最后显示的错误信息如下:
2021-05-18-09-33-07-506609.png
对于“prototype”作用域Bean,Spring容器无法完成依赖注入,因为“prototype”作用域的Bean,Spring容器不进行缓存,因此无法提前暴露一个创建中的Bean。

3、单例setter方法注入—循环依赖解决方法

3.1、使用缓存解决循环依赖

整个Spring创建bean对象的步骤主要是如下三三步
2021-05-18-09-33-07-582408.png
然后在和创建A对象的时候,注入属性时,需要获取B对象,在注入B的时候获取A对象,会造成循环
2021-05-18-09-33-07-664189.png
那么这个时候他Spring提供了一个缓存来解决这种循环的问题
2021-05-18-09-33-07-774894.png
在A对象实例化完后,就先将A对象存入到缓存中暴露出来,让B可以拿到A,拆除循环。Spring的对于解决循环依赖,设置了三级缓存,用来存储不同时期的对象。

3.2、三级缓存

Spring的三级循环分别为

  1. /** 一级缓存
  2. * 单例对象缓存:bean name --> bean的完整实例*/
  3. private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256);
  4. /** 三级缓存
  5. * 保存BeanName于创建bean工程之间的缓存:bean name --> 对象工程,lambda表达式*/
  6. private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<>(16);
  7. /** 二级缓存
  8. * 保存单例对象的半成品:bean name--> 半成品bean(bean实例化好后,没有进行属性填充,没有初始化的半成品对象)*/
  9. private final Map<String, Object> earlySingletonObjects = new HashMap<>(16);

3.3、代码执行过程示意图

这里的代码运行过程是按照上面1.2的代码进行说明的。
2021-05-18-09-33-07-959399.png

4、依赖注入具体执行方法

4.1、调用ClassPathXmlApplicationContext的构造方法

  1. public ClassPathXmlApplicationContext(
  2. String[] configLocations, boolean refresh, @Nullable ApplicationContext parent)
  3. throws BeansException {
  4. super(parent);
  5. //存储spring配置文件的路径到本地
  6. setConfigLocations(configLocations);
  7. //判断是否需要需要重新刷新spring容器——ApplicationContext
  8. if (refresh) {
  9. //刷新spring容器,加载bean的核心方法,刷新spring上下文信息,定义了上下文加载流程——ApplicationContext
  10. refresh();
  11. }
  12. }

refresh ApplicationContext,重新刷新Spring容器,注入必要的类、加载bean的一些配置、并实例化bean。因为AbstractApplicationContextClassPathXmlApplicationContext的父类,所以调用的是AbstractApplicationContextrefresh方法
2021-05-18-09-33-08-231672.png

4.2、进入到AbstractApplicationContext类的refresh()方法

  1. @Override
  2. public void refresh() throws BeansException, IllegalStateException {
  3. synchronized (this.startupShutdownMonitor) {
  4. /**
  5. * 1、设置容器的启动时间
  6. * 2、设置活跃状态为true
  7. * 3、设置关闭状态为false
  8. * 4、获取Environment对象,并加载当前系统的属性到Environment对象中
  9. * 5、准备监听器和时间的结合对象,默认为空的集合
  10. */
  11. // Prepare this context for refreshing.
  12. prepareRefresh();
  13. //创建容器对象:DefaultListableBeanFactory
  14. //加载xml文件的属性,最终要的就是BeanDefinition
  15. ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
  16. //beanFacotry的准备工作,对各种属性进行填充
  17. prepareBeanFactory(beanFactory);
  18. try {
  19. //子类覆盖方法做额外的处理,此出我们一般不做任何扩展工作,可以查看web的代码,是有具体实现
  20. postProcessBeanFactory(beanFactory);
  21. //调用Bean工厂的后置处理器
  22. invokeBeanFactoryPostProcessors(beanFactory);
  23. //注册BeanPostProcessor 自定义以及spring内部的
  24. registerBeanPostProcessors(beanFactory);
  25. // 初始化此上下文的消息源
  26. initMessageSource();
  27. // 初始化事件监听多路广播器
  28. initApplicationEventMulticaster();
  29. // 留给子类来初始化其他的bean
  30. onRefresh();
  31. //在所有注册的bean中查找listener bean,注册到消息广播中
  32. registerListeners();
  33. //初始化剩下的单实例(非懒加载的)
  34. finishBeanFactoryInitialization(beanFactory);
  35. //完成刷新过程,通知生命周期处理器lifecycleProcessor刷新过
  36. finishRefresh();
  37. }
  38. ........
  39. }

其中的核心代码为换初始化剩下的单实例(非懒加载的),也就是43行。是整个Spring容器初始化的核心流程。

4.3、进入到finishBeanFactoryInitialization方法

  1. protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {
  2. ......
  3. // Instantiate all remaining (non-lazy-init) singletons.
  4. //实例化剩下的单例对象
  5. beanFactory.preInstantiateSingletons();
  6. }

那么这个方法里面涉及到实例化的就是beanFactory.preInstantiateSingletons();——实例化剩下的单例对象。
由于ConfigurableListableBeanFactory的实现类为DefaultListableBeanFactory,所以之间调用DefaultListableBeanFactorypreInstantiateSingletons方法。

4.4、进入到preInstantiateSingletons方法

  1. @Override
  2. public void preInstantiateSingletons() throws BeansException {
  3. if (logger.isDebugEnabled()) {
  4. logger.debug("Pre-instantiating singletons in " + this);
  5. }
  6. //将所有的BeanDefinition的名字创建一个集合,beanNames获取到的是[a,b]
  7. List<String> beanNames = new ArrayList<>(this.beanDefinitionNames);
  8. //触发所有非延迟加载单例bean的初始化,遍历集合
  9. for (String beanName : beanNames) {
  10. //合并父类BeanDefinition
  11. //Bean定义的公共抽象类是AbstractBeanDefinition,普通的bean在spring加载bean定义的时候,实例化出来的是GenericBeanDefinition,而Spring上下文
  12. //所有bean用的AbstractBeanDefintion是RootBeanDefinition,这个时候需要转换一些,将非RootBeanDefinition转成RootBeanDefinition进行后续操作
  13. RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
  14. //条件判断,抽象,单例,非懒加载
  15. if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
  16. //判断是否实现了FactoryBean接口
  17. if (isFactoryBean(beanName)) {
  18. //根据&+beanName来获取具体的对象
  19. Object bean = getBean(FACTORY_BEAN_PREFIX + beanName);
  20. if (bean instanceof FactoryBean) {
  21. final FactoryBean<?> factory = (FactoryBean<?>) bean;
  22. boolean isEagerInit;
  23. if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) {
  24. isEagerInit = AccessController.doPrivileged((PrivilegedAction<Boolean>)
  25. ((SmartFactoryBean<?>) factory)::isEagerInit,
  26. getAccessControlContext());
  27. }
  28. else {
  29. isEagerInit = (factory instanceof SmartFactoryBean &&
  30. ((SmartFactoryBean<?>) factory).isEagerInit());
  31. }
  32. //如果急切的希望初始化,通过beanName获取bean的实例
  33. if (isEagerInit) {
  34. getBean(beanName);
  35. }
  36. }
  37. }
  38. else {
  39. //如果beanName对应的bean不是FactoryBean,只是普通的bean,通过beanName获取bean实例
  40. getBean(beanName);
  41. }
  42. }
  43. }
  44. //遍历beanNames,触发所有的SmartInitializingSingleton的后初始化毁掉
  45. ......
  46. }

这个时候beanNames一共有两个一个是a,一个是b,那么先获取a。

4.4.1、第一个判断

a不是抽象,也不是懒加载,是单例,所以会走进

  1. if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit())

4.4.2、第二个判断

a没有实现FactoryBean接口所以直接执行getBean(a)

  1. if (isFactoryBean(beanName)) {
  2. ......
  3. }
  4. else {
  5. //如果beanName对应的bean不是FactoryBean,只是普通的bean,通过beanName获取bean实例
  6. getBean(beanName);
  7. }

4.5、进入到getBean方法

  1. @Override
  2. public Object getBean(String name) throws BeansException {
  3. //此方法获取实际bean的方法,也是触发依赖注入的方法
  4. return doGetBean(name, null, null, false);
  5. }

直接调用doGetBean

4.6、进入到dogetBean方法

  1. @SuppressWarnings("unchecked")
  2. protected <T> T doGetBean(final String name, @Nullable final Class<T> requiredType,
  3. @Nullable final Object[] args, boolean typeCheckOnly) throws BeansException {
  4. //提取对应的beanName
  5. final String beanName = transformedBeanName(name);
  6. Object bean;
  7. // Eagerly check singleton cache for manually registered singletons.
  8. //提前检查单例缓存中是否有手动注册的单例对象,跟循环依赖有关联——6.1
  9. Object sharedInstance = getSingleton(beanName);
  10. //如果bean的单例对象找到了,且没有创建bean实例时要使用的参数
  11. if (sharedInstance != null && args == null) {
  12. .....
  13. }
  14. else {
  15. //判断我们是不是正在创建这个实例,如果是失败,应该是在循环参考之内
  16. if (isPrototypeCurrentlyInCreation(beanName)) {
  17. throw new BeanCurrentlyInCreationException(beanName);
  18. }
  19. //检查该工厂中是否存在bean定义
  20. BeanFactory parentBeanFactory = getParentBeanFactory();
  21. if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
  22. .....
  23. }
  24. //如果不是做类型检查,那么就用创建bean,此处在集合中做一个记录
  25. if (!typeCheckOnly) {
  26. markBeanAsCreated(beanName);
  27. }
  28. try {
  29. //此处做了BeanDefinition对象的转换,当我们从xml文件中加载BeanDefinition对象的时候,封装的对象时GenericBeanDefinition,
  30. //此处要做类型转换,如果是子类bean的话,去合并父类的相关属性
  31. final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
  32. checkMergedBeanDefinition(mbd, beanName, args);
  33. ......
  34. // Create bean instance.
  35. //创建bean的实例对象,这里都可mdb就是RootBeanDefinition,也就是bean相关的一些定义信息
  36. if (mbd.isSingleton()) {
  37. //返回以beanName的(原始)单例对象,如果尚未注册,使用singletonFactory创建并注册一个对象
  38. sharedInstance = getSingleton(beanName, () -> {
  39. try {
  40. //为给定的合并后的BeanDefinition(和参数)创建一个bean实例
  41. return createBean(beanName, mbd, args);
  42. }
  43. catch (BeansException ex) {
  44. //显示地从单例缓存中删除实例,可能是由创建过程急切地放在那里,以允许循环引用解析,还要删除
  45. //接收该bean临时引用的任何bean
  46. //销毁给定的bean,如果找到响应的一次性bean实例,委托给destoryBean
  47. destroySingleton(beanName);
  48. //重新抛出ex
  49. throw ex;
  50. }
  51. });
  52. bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
  53. }
  54. ......
  55. }
  56. catch (BeansException ex) {
  57. cleanupAfterBeanCreationFailure(beanName);
  58. throw ex;
  59. }
  60. }
  61. .....
  62. return (T) bean;
  63. }

进入到doGetBean,这个时候才是真正获取bean的时候

4.6.1、先尝试从缓存中获取bean——getSingleton(beanName)

  1. //提前检查单例缓存中是否有手动注册的单例对象
  2. Object sharedInstance = getSingleton(beanName);

具体这块执行的代码是

  1. @Nullable
  2. protected Object getSingleton(String beanName, boolean allowEarlyReference) {
  3. //从单例对象缓存中获取beanName对应的单例对象<<一级缓存>>
  4. Object singletonObject = this.singletonObjects.get(beanName);
  5. //如果单例对象缓存中没有,并且该beanName对应的单例bean正在创建中
  6. if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
  7. //如果为空,则锁定全局变量并进行处理
  8. synchronized (this.singletonObjects) {
  9. //从早期单例对象缓存中获取单例对象(之所以被称为早期单例对象,是因为earlySingletonObjects里
  10. // 的所有对象都是通过提前曝光的ObjectFactory创建出来的,还未进行属性填充等操作)
  11. singletonObject = this.earlySingletonObjects.get(beanName);
  12. //如果早期单例对象缓存中也没有,并且允许创建早期单例对象引用
  13. if (singletonObject == null && allowEarlyReference) {
  14. ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
  15. if (singletonFactory != null) {
  16. singletonObject = singletonFactory.getObject();
  17. this.earlySingletonObjects.put(beanName, singletonObject);
  18. this.singletonFactories.remove(beanName);
  19. }
  20. }
  21. }
  22. }
  23. return singletonObject;
  24. }

这个时候一级缓存是没有a对象的,所以singletonObject获取的为null然后a也没有在创建过程中,所以直接返回null。

4.6.2、开始调用getSingleton(beanName,singleFacotry)

  1. if (mbd.isSingleton()) {
  2. //返回以beanName的(原始)单例对象,如果尚未注册,使用singletonFactory创建并注册一个对象
  3. sharedInstance = getSingleton(beanName, () -> {
  4. try {
  5. //为给定的合并后的BeanDefinition(和参数)创建一个bean实例
  6. return createBean(beanName, mbd, args);
  7. }
  8. ......
  9. });
  10. bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
  11. }

这块具体执行的为

  1. public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {
  2. //如果beanName为null,抛出异常
  3. Assert.notNull(beanName, "Bean name must not be null");
  4. //使用单实例对象的高速缓冲Map作为锁,保证线程同步
  5. synchronized (this.singletonObjects) {
  6. //从单例对象的高速缓冲Map中获取beanName对应的单例对象
  7. Object singletonObject = this.singletonObjects.get(beanName);
  8. //如果获取到的为空
  9. if (singletonObject == null) {
  10. //如果当前在destorySingletons中
  11. if (this.singletonsCurrentlyInDestruction) {
  12. ......
  13. }
  14. ......
  15. //创建单例之前的回调,默认实现将单例注册为当前正在创建中
  16. beforeSingletonCreation(beanName);
  17. ......
  18. try {
  19. //从单例工厂中获取对象
  20. singletonObject = singletonFactory.getObject();
  21. //生成了新的单例对象的标记成true,表示生成了新的单例对象
  22. newSingleton = true;
  23. }
  24. ......
  25. finally {
  26. //如果没有抑制异常记录
  27. if (recordSuppressedExceptions) {
  28. this.suppressedExceptions = null;
  29. }
  30. //创建单例后的回调,默认实现将单例标记为不在创建中
  31. afterSingletonCreation(beanName);
  32. }
  33. //生成了新的单例对象
  34. if (newSingleton) {
  35. //将beanName和singletonObject的映射关系添加到该工厂的单例缓存中,也就是一级缓存中
  36. addSingleton(beanName, singletonObject);
  37. }
  38. }
  39. return singletonObject;
  40. }
  41. }

这个一级缓存获取到的为null,然后将bean的状态变成创建中,之后调用 singletonFactory.getObject()方法。也就是进入到传给getSingleton方法的lamabdagetBean方法

4.7、进入到getBean方法

  1. @Override
  2. protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
  3. throws BeanCreationException {
  4. ......
  5. try {
  6. //实际创建bean的调用
  7. Object beanInstance = doCreateBean(beanName, mbdToUse, args);
  8. if (logger.isDebugEnabled()) {
  9. logger.debug("Finished creating instance of bean '" + beanName + "'");
  10. }
  11. return beanInstance;
  12. }
  13. ......
  14. }

这里调用真正创建bean的方法,doGetBean

4.8、进入到doGetBean

  1. protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args)
  2. throws BeanCreationException {
  3. //这个beanWrapper是用来持有创建出来的Bean对象的
  4. BeanWrapper instanceWrapper = null;
  5. //获取factoryBean实例缓存
  6. if (mbd.isSingleton()) {
  7. //如果是单例对象,从factorybean实例缓存中移除当前bean的定义信息
  8. instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
  9. }
  10. //如果实例为空
  11. if (instanceWrapper == null) {
  12. //实例化bean
  13. //根据bean使用对应的策略创建新的实例,如:工厂方法,构造函数主动注入,简单初始化
  14. instanceWrapper = createBeanInstance(beanName, mbd, args);
  15. }
  16. //从包装类中获取原始bean
  17. ......
  18. //运行beanPostProcessor去修改合并的beanDefinition
  19. ......
  20. //缓存单例以便处理循环引用,即使是像BeanFactoryAware这样的生命周期接口触发的
  21. boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
  22. isSingletonCurrentlyInCreation(beanName));
  23. if (earlySingletonExposure) {
  24. ......
  25. //添加到缓存当中
  26. addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
  27. }
  28. //初始化bean实例
  29. Object exposedObject = bean;
  30. try {
  31. //注入过程
  32. populateBean(beanName, mbd, instanceWrapper);
  33. // 将会触发postProcessBeforeInitialization和postProcessAfterInitialization
  34. exposedObject = initializeBean(beanName, exposedObject, mbd);
  35. }
  36. catch (Throwable ex) {
  37. ......
  38. }
  39. ......
  40. }
  41. //注册完成依赖注入的Bean
  42. try {
  43. registerDisposableBeanIfNecessary(beanName, bean, mbd);
  44. }
  45. .....
  46. return exposedObject;
  47. }

4.8.1、开始调用createBeanInstance(beanName, mbd, args);

  1. protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) {
  2. //解析calss
  3. Class<?> beanClass = resolveBeanClass(mbd, beanName);
  4. ......
  5. // 一个类可能有多个构造器,所以Spring得根据参数个数、类型确定需要调用的构造器
  6. // 在使用构造器创建实例后,Spring会将解析过后确定下来的构造器或工厂方法保存在缓存中,避免再次创建相同bean时再次解析
  7. boolean resolved = false;
  8. boolean autowireNecessary = false;
  9. if (args == null) {
  10. synchronized (mbd.constructorArgumentLock) {
  11. //判断是否有解析的构造方法或者工厂方法
  12. if (mbd.resolvedConstructorOrFactoryMethod != null) {
  13. //已经解析过的class构造器
  14. resolved = true;
  15. autowireNecessary = mbd.constructorArgumentsResolved;
  16. }
  17. }
  18. }
  19. //如果解析过
  20. if (resolved) {
  21. ......
  22. }
  23. //需要根据参数解析、确认构造器的函数(从Bean后处理器确定构造函数)
  24. Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);
  25. // 解析的构造器不为空 || 注入类型为构造函数自动注入 || bean定义中有构造器参数 || 传入参数不为空
  26. if (ctors != null || mbd.getResolvedAutowireMode() == AUTOWIRE_CONSTRUCTOR ||
  27. ......
  28. }
  29. // No special handling: simply use no-arg constructor.
  30. //使用默认构造器
  31. return instantiateBean(beanName, mbd);
  32. }

调用具体的创建bean的方式,有好几种,本例子采用的是//使用默认构造器 return instantiateBean(beanName, mbd);

4.8.2、将实例化后的a放入到缓存中

判断是否符合需要提前暴露对象,加入缓存的条件

  1. boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
  2. isSingletonCurrentlyInCreation(beanName));
  • 目前a单例的
  • allowCircularReferences是允许循环依赖的,这个字段Spring默认为true,也可以通过改变这个字段,而禁止循环依赖
  • isSingletonCurrentlyInCreation(a),a也是在创建过程中的,在2.3.6的②中已经执行了将a设置为创建中的状态均符合要求所以会执行加入缓存的操作

    1. if (earlySingletonExposure) {
    2. ......
    3. //添加到缓存当中
    4. addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
    5. }

    加入缓存具体执行的方法为:

    1. protected void addSingletonFactory(String beanName, ObjectFactory<?> singletonFactory) {
    2. Assert.notNull(singletonFactory, "Singleton factory must not be null");
    3. //使用singletonObjects进行加锁,保证线程安全
    4. synchronized (this.singletonObjects) {
    5. //如果单例对象的高速缓存【Bean名称-bean实例】没有beanName对象
    6. if (!this.singletonObjects.containsKey(beanName)) {
    7. //将beanName.singletonFactory放入到单例工厂的缓存当中【bean名称-ObjectFactory】
    8. this.singletonFactories.put(beanName, singletonFactory);
    9. //从早期单例对象的高速缓存【bean名称-bean实例】,移除beanName的相关缓存对象
    10. this.earlySingletonObjects.remove(beanName);
    11. //将beanName添加到已注册的单例集中
    12. this.registeredSingletons.add(beanName);
    13. }
    14. }
    15. }

    下面就该进行到调用populateBean方法为a注入属性

    4.9、调用方法populateBean注入属性

    1. protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) {
    2. // 如果bean实例为空(空实例),并且其属性不为空,则抛出错误,否则跳过
    3. ......
    4. // 在设置属性之前调用Bean的PostProcessor后置处理器
    5. if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
    6. for (BeanPostProcessor bp : getBeanPostProcessors()) {
    7. if (bp instanceof InstantiationAwareBeanPostProcessor) {
    8. InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
    9. if (!ibp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {
    10. return;
    11. }
    12. }
    13. }
    14. }
    15. // 依赖注入开始,首先处理autowire自动装配的注入——因为我这里没有使用autowire所以省略
    16. ......
    17. // 检查容器是否持有用于处理单态模式Bean关闭时的后置处理器
    18. ......
    19. if (pvs != null) {
    20. //主线
    21. // 对属性进行注入操作,解决任何在这个bean工厂运行时其他bean的引用,必须使用深拷贝,所以不会永久修改这个属性
    22. applyPropertyValues(beanName, mbd, bw, pvs);
    23. }
    24. }

    4.9.1、 调用设置xml属性的核心方法applyPropertyValues

    1. protected void applyPropertyValues(String beanName, BeanDefinition mbd, BeanWrapper bw, PropertyValues pvs) {
    2. //如果pvsPropertyValue
    3. if (pvs.isEmpty()) {
    4. //直接结束方法
    5. return;
    6. }
    7. ......
    8. List<PropertyValue> deepCopy = new ArrayList<>(original.size());
    9. boolean resolveNecessary = false;
    10. //遍历属性,将属性转换成对应类的对应属性类型
    11. for (PropertyValue pv : original) {
    12. //如果该属性已经被解析过
    13. if (pv.isConverted()) {
    14. //将pv添加到deepCopy中
    15. deepCopy.add(pv);
    16. }
    17. //如果没有
    18. else {
    19. //获取属性名
    20. String propertyName = pv.getName();
    21. //获取未经类型转换的值
    22. Object originalValue = pv.getValue();
    23. //由valueResolver根据pv解析出originalValue所封装的对象
    24. Object resolvedValue = valueResolver.resolveValueIfNecessary(pv, originalValue);
    25. ......
    26. }
    27. }
    28. ......
    29. }

    4.9.2、 调用resolveValueIfNecessary方法解决属性的值

    1. @Nullable
    2. public Object resolveValueIfNecessary(Object argName, @Nullable Object value) {
    3. //如果values是RuntimeBeanReference实例
    4. if (value instanceof RuntimeBeanReference) {
    5. //将value强转成RuntimeBeanReference对象
    6. RuntimeBeanReference ref = (RuntimeBeanReference) value;
    7. //解析出对应的ref所封装的bean元信息(bean名称和类型)的Bean对象
    8. //处理引用
    9. return resolveReference(argName, ref);
    10. }
    11. ......
    12. }

    4.9.3、 调用解决属性的ref外部引用resolveReference方法

    1. @Nullable
    2. private Object resolveReference(Object argName, RuntimeBeanReference ref) {
    3. try {
    4. //定义一个存储b对象的变量
    5. Object bean;
    6. //获取两一个bean引用的bean类型
    7. String refName = ref.getBeanName();
    8. refName = String.valueOf(doEvaluate(refName));
    9. //如果引用来自父工厂
    10. if (ref.isToParent()) {
    11. ......
    12. }
    13. else {
    14. //获取resolvedName的bean对象
    15. bean = this.beanFactory.getBean(refName);
    16. //注册beanName与dependentBeanNamed的依赖关系到bean工厂
    17. this.beanFactory.registerDependentBean(refName, this.beanName);
    18. }
    19. if (bean instanceof NullBean) {
    20. bean = null;
    21. }
    22. return bean;
    23. }
    24. ......
    25. }

    执行到下面的getBean,就开始获取b

    1. //获取resolvedName的bean对象
    2. bean = this.beanFactory.getBean(refName);

    4.10、创建b的过程

  • 创建b的过程会循环前面的4.5—4.9.2,直道注入b的属性时,获取a,也就是运行到4.9.3的getBean(a)开始获取b的属性值a

  • 再次到循环4.5获取a对象,也就是b的属性a的value
  • 这个时候先执行4.6.1的getSingleton方法,这个时候a在一级缓存中没有,但是a是出于创建过程中的,所以可以拿到a并将a放入二级缓存,移出三级缓存

    1. singletonObject = this.earlySingletonObjects.get(beanName);
    2. //如果早期单例对象缓存中也没有,并且允许创建早期单例对象引用
    3. if (singletonObject == null && allowEarlyReference) {
    4. ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
    5. if (singletonFactory != null) {
    6. singletonObject = singletonFactory.getObject();
    7. this.earlySingletonObjects.put(beanName, singletonObject);
    8. this.singletonFactories.remove(beanName);
    9. }
    10. }
  • 从三级缓存中获取到a后,再执行4.6中的真正获取工厂中的a的getObjectForBeanInstance方法

    1. bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
  • 将拿到的a返回到4.9.3的getBean方法中,a的注入属性完成,之后执行4.8的初始化方法

    1. // 将会触发postProcessBeforeInitialization和postProcessAfterInitialization
    2. exposedObject = initializeBean(beanName, exposedObject, mbd);
  • 将拿到的a返回到4.9.3的getBean方法中,a的注入属性完成,之后执行4.8的初始化方法

    1. // 将会触发postProcessBeforeInitialization和postProcessAfterInitialization
    2. exposedObject = initializeBean(beanName, exposedObject, mbd);
  • b初始化完成后,返回b对象到4.6.2,将b对象放入到一级缓存中

    1. //生成了新的单例对象
    2. if (newSingleton) {
    3. //将beanName和singletonObject的映射关系添加到该工厂的单例缓存中,也就是一级缓存中
    4. addSingleton(beanName, singletonObject);
    5. }
    6. //addSingleton方法内部执行
    7. protected void addSingleton(String beanName, Object singletonObject) {
    8. synchronized (this.singletonObjects) {
    9. //将映射关系添加到单例对象的高速缓冲中
    10. this.singletonObjects.put(beanName, singletonObject);
    11. //移除beanName在三级缓存中的数据——工厂缓存
    12. this.singletonFactories.remove(beanName);
    13. //移除beanName在二级缓存中的对象
    14. this.earlySingletonObjects.remove(beanName);
    15. //将beanName添加到已经注册的单例集中
    16. this.registeredSingletons.add(beanName);
    17. }
    18. }

    4.11、将a创建完成

  • b对象创建完成之后,将b对象返回到a的属性注入时获取a的getBean(b)方法,将a类似b注入完成后的过程一样,创建完成a