循环引用属性操作:

1)AbstractAutowireCapableBeanFactory类中的allowCircularReferences被设置为了false。

2)代码:

AnnotationConfigApplicationContext a = new AnnotationConfigApplicationContext("");

a.setAllowCircularReferences();

spring初始化过程

1 初始化spring上下文,new DefaultListBeanFactory()

2 之后调用refresh()

3 refresh()中包含了springBean初始化的全部过程

4 完成spring扫描所有的Bean,在invokeBeanFactoryPostProcessors()

5 其中最核心的初始化方法是finishBeanFactoryInitialization(传入beanFactory)

6 之后继续调用preInstantiateSingletons,进入初始化的准备。

7 核心方法继续调用getBean,因为getBean才会真正的初始化Bean。那么在getBean中会调用两次getSingleton方法,“第一次调用是解决Bean相互引用问题,第二个参数默认传递为true”。

8 首次调用getSingleton基本会返回null因为这个时候 bean没有被创建成功,所以在singleobjectsMap中还没有办法找到创建成功的Bean,这个时候继续会判断当前Bean的是否处于创建状态,如果是的话从earlySingletonObjectsMap中获取一定获取的到;如果不在创建状态,那么这个时候首次调用返回null。
***在这里说明下,bean在最开始仅仅是个“创建中”的状态,也就是单独创建了对象,但是依赖注入还没有做,这样的对象会放入earlySingletonObjectsMap中!

9 二次调用getSingleton方法,初始化bean的时候还会检查singleobjectsMap集合,如果仍然获取不到则去执行createBean方法创建对象,委托模式调用了doCreateBean方法的createInstance方法创建了wapper对象。

9.1 其实在这里创建的包装对象还仅仅是一个java对象,还没有进行属性的注入因为注入要通过populateBean方法处理。

ps:spring的BeanFactory后置处理器共有8个。

10 注入方法是通过 populateBean 方法开始执行的,遇到@Autowired属性则通过BeanFactory的后置处理器找到相应的BeanDefine再次调用getBean方法执行第6步骤即可。

10.1 populateBean 方法执行时首先判断当前类需不需要注入;

10.2 调用doCreateBean之后在调用initializeBean方法,该方法中使用“策略模式”对Bean的继承接口进行扩展;

10.3 initializeBean方法中的invokeAwareMethods方法会回调Bean实现了以下接口的方法:BeanNameAware,BeanClassLoaderAware,BeanFactoryAware

private void invokeAwareMethods(String beanName, Object bean) {
if(bean instanceof Aware) {
if(bean instanceof BeanNameAware) {
((BeanNameAware)bean).setBeanName(beanName);
} if(bean instanceof BeanClassLoaderAware) {
((BeanClassLoaderAware)bean).setBeanClassLoader(this.getBeanClassLoader());
} if(bean instanceof BeanFactoryAware) {
((BeanFactoryAware)bean).setBeanFactory(this);
}
} }

10.4 往下跟踪applyBeanPostProcessorsBeforeInitialization方法中继续使用Bean的后置处理器,回调对应接口的方法:

    public Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName) throws BeansException {
Object result = existingBean;
Iterator var4 = this.getBeanPostProcessors().iterator(); do {
if(!var4.hasNext()) {
return result;
} BeanPostProcessor beanProcessor = (BeanPostProcessor)var4.next();
result = beanProcessor.postProcessBeforeInitialization(result, beanName);
} while(result != null); return result;
} @Override
public Object postProcessBeforeInitialization(final Object bean, String beanName) throws BeansException {
AccessControlContext acc = null; if (System.getSecurityManager() != null &&
(bean instanceof EnvironmentAware || bean instanceof EmbeddedValueResolverAware ||
bean instanceof ResourceLoaderAware || bean instanceof ApplicationEventPublisherAware ||
bean instanceof MessageSourceAware || bean instanceof ApplicationContextAware)) {
acc = this.applicationContext.getBeanFactory().getAccessControlContext();
} if (acc != null) {
AccessController.doPrivileged(new PrivilegedAction<Object>() {
@Override
public Object run() {
invokeAwareInterfaces(bean);
return null;
}
}, acc);
}
else {
invokeAwareInterfaces(bean);
} return bean;
}

ps:之前提到过两次getSingleton方法是为了处理Bean相互引用的问题的答案也就渐渐浮出水面;如下图:

spring 循环引用问题,在一次问题调试过程中发现有个小伙伴竟然把循环引用设置成false了。估计是百度的时候没小心额外的代码吧。。。的更多相关文章

  1. Spring源码浅析之bean实例的创建过程(二)

    在上一篇内容中,介绍了doGetBean方法的源码内容,知道了bean在创建的过程中,有三个范围,单例.多例.Scope,里面都使用到了createBean.下面本篇文章的主要内容,就是围绕creat ...

  2. 【Spring Framework】Spring IOC详解及Bean生命周期详细过程

    Spring IOC 首先,在此之前,我们就必须先知道什么是ioc,ioc叫做控制反转,也可以称为依赖注入(DI),实际上依赖注入是ioc的另一种说法, 1.谁控制谁?: 在以前,对象的创建和销毁都是 ...

  3. ThreadLocalMap的enrty的key为什么要设置成弱引用

    ThreadLocalMap的Enrty代码实现: 将Entry的Key设置成弱引用,在配合线程池使用的情况下可能会有内存泄露的风险.之设计成弱引用的目的是为了更好地对ThreadLocal进行回收, ...

  4. 【spring mvc】springmvc在tomcat中的执行过程

    一.WEB容器在启动时,它会为每个WEB应用程序都创建一个对应的ServletContext对象(每个web应用程序唯一),它代表当前web应用web容器提供其一个全局的上下文环境,其为后面的spri ...

  5. js:for循环ul/li,获取当前被点击元素的id,以及给其他li设置属性

    js:for循环ul/li,获取当前被点击元素的id,以及给其他li设置属性 <!doctype html> <html> <head> <meta char ...

  6. 【Java面试宝典】说说你对 Spring 的理解,非单例注入的原理?它的生命周期?循环注入的原理, aop 的实现原理,说说 aop 中的几个术语,它们是怎么相互工作的?

    AOP与IOC的概念(即spring的核心) IOC:Spring是开源框架,使用框架可以使我们减少工作量,提高工作效率并且它是分层结构,即相对应的层处理对应的业务逻辑,减少代码的耦合度.而sprin ...

  7. Spring源码浅析之bean实例的创建过程(一)

    在之前的文章内容中,简单介绍了bean定义的加载过程,下面这篇的主要内容就是bean实例的创建过程. bean实例的创建方式 ApplicationContext context = new Clas ...

  8. 用fluent模拟内循环床气化燃烧(调试过程记录)

    模拟对象为文献Combined gasification of coal and biomass in internal circulating fluidized bed[1]中的内循环气化炉.[1]h ...

  9. Spring 源码学习 - 单例bean的实例化过程

    本文作者:geek,一个聪明好学的同事 1. 简介 开发中我们常用@Commpont,@Service,@Resource等注解或者配置xml去声明一个类,使其成为spring容器中的bean,以下我 ...

随机推荐

  1. 趣味编程:FizzBuzz(Haskell版)

    g :: Int -> Int -> Int -> String g n 0 0 = "FizzBuzz" g n 0 _ = "Fizz" ...

  2. 我永远讨厌gch文件

    一个学期没写博客了. 今天写OOP作业见鬼了, 调了半天. 我写了一个match.h和一个match.cpp, 然后match.cpp里面#include"match.h", 然后 ...

  3. ArrayList存储随机数字

    package com.fgy.demo; import java.util.ArrayList; import java.util.Random; /** * ArrayList实现存储随机数字 * ...

  4. LeetCode 837. New 21 Game

    原题链接在这里:https://leetcode.com/problems/new-21-game/ 题目: Alice plays the following game, loosely based ...

  5. WinDbg常用命令系列---!address

    !address 这个!address扩展命令显示有关目标进程或目标计算机使用的内存的信息. 用户模式: !address Address !address -summary !address [-f ...

  6. [RN] React Native 常用命令行

    [RN] React Native 常用命令行 1.查看当前版本 react-native --version 或 react-native -v 2.创建指定版本的React Native项目 1) ...

  7. vscode前端插件(我的标配)

    前言 今天给我的vscode编辑汉化了一下)我也不知道为什么要汉化一下... 但是汉化后 我的vue文件木有高亮了,2333(只好一顿操作 再安装插件 还要去百度找 自己留存) 汉化后 是所有的插件都 ...

  8. [转]ProxmoxVE 干掉 VMware

    很久没有写这种通俗易懂的文章了,不是我愤世嫉俗,而是因为确实太为那些花大价钱购买VMware的冤大头鸣不平. 确实VMware在虚拟化市场占有率非常高,技术也非常成熟,用户使用起来很方便,但是如果你是 ...

  9. Oracle系列四 单行函数查询语句

    单行函数 操作数据对象 接受参数返回一个结果 只对一行进行变换 每行返回一个结果 可以转换数据类型 可以嵌套 参数可以是一列或一个值 包含:字符,数值,日期,转换,通用 字符函数 1.大小写控制函数: ...

  10. 持久化机器学习模型(joblib方式)

    import numpy as np import matplotlib.pyplot as plt from sklearn.linear_model import LinearRegression ...