循环引用属性操作:

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

  1. private void invokeAwareMethods(String beanName, Object bean) {
  2. if(bean instanceof Aware) {
  3. if(bean instanceof BeanNameAware) {
  4. ((BeanNameAware)bean).setBeanName(beanName);
  5. }
  6.  
  7. if(bean instanceof BeanClassLoaderAware) {
  8. ((BeanClassLoaderAware)bean).setBeanClassLoader(this.getBeanClassLoader());
  9. }
  10.  
  11. if(bean instanceof BeanFactoryAware) {
  12. ((BeanFactoryAware)bean).setBeanFactory(this);
  13. }
  14. }
  15.  
  16. }

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

  1. public Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName) throws BeansException {
  2. Object result = existingBean;
  3. Iterator var4 = this.getBeanPostProcessors().iterator();
  4.  
  5. do {
  6. if(!var4.hasNext()) {
  7. return result;
  8. }
  9.  
  10. BeanPostProcessor beanProcessor = (BeanPostProcessor)var4.next();
  11. result = beanProcessor.postProcessBeforeInitialization(result, beanName);
  12. } while(result != null);
  13.  
  14. return result;
  15. }
  16.  
  17. @Override
  18. public Object postProcessBeforeInitialization(final Object bean, String beanName) throws BeansException {
  19. AccessControlContext acc = null;
  20.  
  21. if (System.getSecurityManager() != null &&
  22. (bean instanceof EnvironmentAware || bean instanceof EmbeddedValueResolverAware ||
  23. bean instanceof ResourceLoaderAware || bean instanceof ApplicationEventPublisherAware ||
  24. bean instanceof MessageSourceAware || bean instanceof ApplicationContextAware)) {
  25. acc = this.applicationContext.getBeanFactory().getAccessControlContext();
  26. }
  27.  
  28. if (acc != null) {
  29. AccessController.doPrivileged(new PrivilegedAction<Object>() {
  30. @Override
  31. public Object run() {
  32. invokeAwareInterfaces(bean);
  33. return null;
  34. }
  35. }, acc);
  36. }
  37. else {
  38. invokeAwareInterfaces(bean);
  39. }
  40.  
  41. return bean;
  42. }

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. SpringCloud过滤filter

    目录 配置文件 application.yml eureka: client: service-url: defaultZone: http://localhost:8001/eureka serve ...

  2. JavaScript的深入理解(1)

    (1)什么是JavaScript? JavaScript是一种专为与网页交互而设计的脚本语言,由三个部分组成:(1).ECMAScript :提供核心语言功能.(2).文档对象模型(DOM):提供访问 ...

  3. 2019.12.09 java循环(while)

    class Demo04 { public static void main(String[] args) { int sum=0; int i=1; while(i<=100){ //sum ...

  4. WinDbg常用命令系列---异常相关操作

    .exr (Display Exception Record) .exr命令显示异常记录的内容. .exr Address .exr -1 参数: Address指定异常记录的地址.如果指定-1作为地 ...

  5. [RN] React Native 实现 FlatList上拉加载

     FlatList可以利用官方组件 RefreshControl实现下拉刷新功能,但官方没有提供相应的上拉加载的组件,因此在RN中实现上拉加载比下拉刷新要复杂一点. 不过我们仍可以通过FlatList ...

  6. CSS3之碰撞反弹动画无限运动

    示例代码如下: <!DOCTYPE html> <html lang="en"> <head> <meta charset="U ...

  7. 关于html异步加载外部json文件报错问题

    一. HTML代码如下: 参考网站(echarts-JSON请求数据):https://blog.csdn.net/you23hai45/article/details/51585506 <!D ...

  8. ajax post data 获取不到数据,注意 content-type的设置 、post/get(转)

    ajax post  data  获取不到数据,注意 content-type的设置 .post/get 关于 jQuery data 传递数据.网上各种获取不到数据,乱码之类的. 好吧今天我也遇到了 ...

  9. 四种CSS样式的引入方式

    准备 1.首先准备一个html文件:test.html,不建议使用记事本创建文件,建议使用Notepad++来创建并编辑文件,注意编码格式为:以UTF-8无BOM格式编码,否则会出现中文乱码,内容如下 ...

  10. mysql avg()函数,获取字段的平均值

    mysql> select * from table1; +----------+------------+-----+---------------------+ | name_new | t ...