循环引用属性操作:

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. django-安装nginx及fastdfs-nginx-module

    安装nginx及fastdfs-nginx-module 1. 解压缩 nginx-1.8.1.tar.gz 2. 解压缩 fastdfs-nginx-module-master.zip 3. 进入n ...

  2. EventWaitHandle 第一课

    本篇通过一个列子使用EventWaitHandle实现两个线程的同步.请参看下面的列子. using System; using System.Collections.Generic; using S ...

  3. springboot使用jdbcTemplate案例

    1 创建实体类 public class Student { private Integer stuid; private String stuname; public Integer getStui ...

  4. [Dynamic Programming] 198. House Robber

    You are a professional robber planning to rob houses along a street. Each house has a certain amount ...

  5. [Go] Slices vs Array

    It is recommended to use 'slice' over 'Array'. An array variable denotes the entire array; it is not ...

  6. linux patch 简单学习

    使用patch 我们可以方便的进行软件补丁包处理,以下演示一个简单的c 项目补丁处理 原代码 app.c #include <stdio.h> int main(){ printf(&qu ...

  7. 3D数据采集和重建

    3D数据采集和重建是从传感器数据生成三维或时空模型.一般而言,这些技术和理论适用于大多数或所有传感器类型,包括光学,声学,激光扫描,[1]雷达,热学,[2]地震.[3][4] 内容 ·        ...

  8. lower_bound( )和upper_bound( )怎么用嘞↓↓↓

    lower_bound( )和upper_bound( )都是利用二分查找的方法在一个排好序的数组中进行查找的. 在从小到大的排序数组中, lower_bound( begin,end,num):从数 ...

  9. mysql 转大写

    当前表: mysql> select * from table1; +----------+------------+-----+ | name_new | transactor | pid | ...

  10. SDN第六次上机作业

    1.实验拓扑 实验拓扑图如下: 搭建代码如下: 创建py脚本文件,并编写代码,如下: class MyTopo(Topo): def __init__(self): # initilaize topo ...