spring 循环引用问题,在一次问题调试过程中发现有个小伙伴竟然把循环引用设置成false了。估计是百度的时候没小心额外的代码吧。。。
循环引用属性操作:
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了。估计是百度的时候没小心额外的代码吧。。。的更多相关文章
- Spring源码浅析之bean实例的创建过程(二)
在上一篇内容中,介绍了doGetBean方法的源码内容,知道了bean在创建的过程中,有三个范围,单例.多例.Scope,里面都使用到了createBean.下面本篇文章的主要内容,就是围绕creat ...
- 【Spring Framework】Spring IOC详解及Bean生命周期详细过程
Spring IOC 首先,在此之前,我们就必须先知道什么是ioc,ioc叫做控制反转,也可以称为依赖注入(DI),实际上依赖注入是ioc的另一种说法, 1.谁控制谁?: 在以前,对象的创建和销毁都是 ...
- ThreadLocalMap的enrty的key为什么要设置成弱引用
ThreadLocalMap的Enrty代码实现: 将Entry的Key设置成弱引用,在配合线程池使用的情况下可能会有内存泄露的风险.之设计成弱引用的目的是为了更好地对ThreadLocal进行回收, ...
- 【spring mvc】springmvc在tomcat中的执行过程
一.WEB容器在启动时,它会为每个WEB应用程序都创建一个对应的ServletContext对象(每个web应用程序唯一),它代表当前web应用web容器提供其一个全局的上下文环境,其为后面的spri ...
- js:for循环ul/li,获取当前被点击元素的id,以及给其他li设置属性
js:for循环ul/li,获取当前被点击元素的id,以及给其他li设置属性 <!doctype html> <html> <head> <meta char ...
- 【Java面试宝典】说说你对 Spring 的理解,非单例注入的原理?它的生命周期?循环注入的原理, aop 的实现原理,说说 aop 中的几个术语,它们是怎么相互工作的?
AOP与IOC的概念(即spring的核心) IOC:Spring是开源框架,使用框架可以使我们减少工作量,提高工作效率并且它是分层结构,即相对应的层处理对应的业务逻辑,减少代码的耦合度.而sprin ...
- Spring源码浅析之bean实例的创建过程(一)
在之前的文章内容中,简单介绍了bean定义的加载过程,下面这篇的主要内容就是bean实例的创建过程. bean实例的创建方式 ApplicationContext context = new Clas ...
- 用fluent模拟内循环床气化燃烧(调试过程记录)
模拟对象为文献Combined gasification of coal and biomass in internal circulating fluidized bed[1]中的内循环气化炉.[1]h ...
- Spring 源码学习 - 单例bean的实例化过程
本文作者:geek,一个聪明好学的同事 1. 简介 开发中我们常用@Commpont,@Service,@Resource等注解或者配置xml去声明一个类,使其成为spring容器中的bean,以下我 ...
随机推荐
- vue cli4.0 快速搭建项目详解
搭建项目之前,请确认好你自己已经安装过node, npm, vue cli.没安装的可以参考下面的链接安装. 如何安装node? 安装好node默认已经安装好npm了,所以不用单独安装了. 如何安装v ...
- gj的zabbix客户端开机自启动设置
查看是否自启动 配置chkconfig 启动服务
- 洛谷 P2312 解方程 题解
P2312 解方程 题目描述 已知多项式方程: \[a_0+a_1x+a_2x^2+\cdots+a_nx^n=0\] 求这个方程在 [1,m][1,m] 内的整数解(\(n\) 和 \(m\) 均为 ...
- rust学习
Rust (github) 1. install (https://rustup.rs/) 2. play on line curl https://sh.rustup.rs -sSf | sh e ...
- C++2.0新特性(八)——<Smart Pointer(智能指针)之unique_ptr>
一.概念介绍 unique_ptr它是一种在异常发生时可帮助避免资源泄露的smart pointer,实现了独占式拥有的概念,意味着它可确保一个对象和其他相应资源在同一时间只被一个pointer拥有, ...
- HttpClient 发送请求和参数
发送请求 没有参数 private static void getData() { String timeStamp = String.valueOf(System.currentTimeMillis ...
- Redis配置讲解及实战
前言 Redis是一个开源的内存k-v数据库,同时也可用作缓存,消息队列.支持多种数据类型,如字符串,列表,字典,集合,有序集合. 演示环境 $ uname -a Darwin Darwin Kern ...
- Dolly
dolly - 必应词典 美['dɑli]英['dɒli] n.洋娃娃:(搬运重物的)台车 v.用独轮车运(物):用搅拌棒洗(衣):用捣棒捣碎(矿石) 网络多莉:多利:移动式摄影小车 变形复数:dol ...
- plsql查询数据库-中文显示问号问题
解决方法: 设置本地环境变量 :NLS_LANG=AMERICAN_AMERICA.ZHS16GBK https://blog.csdn.net/github_38358734/article/det ...
- Linux下emacs如何安装
ftp://ftp.gnu.org/gnu/emacs/ 下载对应版本编译安装 cd 自己想安装的目录 sudo wget ftp://ftp.gnu.org/gnu/emacs/emacs-24.4 ...