@Service
public class A extends GenericBaseService {
@Autowired
private B b;
}
@Service
public class B extends GenericBaseService {
@Autowired
private A a;
}


spring中的bean和java对象的区别:
假如有个类Student,对于java对象 Student st=new Student();
但对于bean: 创建出java对象后还要经过一系列的处理器处理,如是否需要动态代理,是否需要注入各种属性


spring底层是支持循环依赖的,A依赖B B依赖A,这里说的A和B都是spring bean;
如果把bean的创建过程简述为2个步骤的话: 1. 创建 一个对象(底层通过反射) 2. 给对象注入属性,那么A和B的创建流程如下
1. A的创建: A a=new A();
2. 属性注入:发现需要B
3. 创建B b=new B();
4. 属性注入: 发现需要A,此时A已经创建了.只是还没经过各种后置处理器处理,所以B是可以完成属性注入的,只是一个半成品
5.之后回到第2步,就可以给A赋值了,循环依赖到此解决


//然而生产中的情况复杂多,相互依赖的关系网太复杂了,所以经常还是会出现提示循环依赖的异常,此时可以用另外一个方式去解决,那就是@Lazy注解了


@Service
public class A extends GenericBaseService {
@Autowired
@Lazy
private B b;
}


加了lazy的原理如下:
1. A的创建: A a=new A();
2. 属性注入:发现需要B,查询字段b的所有注解,发现有@lazy注解,那么就不直接创建B了,而是使用动态代理创建一个代理类B
3. 此时A跟B就不是相互依赖了,变成了A依赖一个代理类B1,B依赖A


验证这个方式很简单:
从容器中分别获取A a 和B b 的实例对象,然后从A中获取它依赖的对象b1,打印b1的class对象,判断b1是否和b相等

 //下面使用Student和School类来测试
@Component
public class School {
@Autowired
@Lazy
private Student student; public Student getStudent() {
return student;
} public void setStudent(Student student) {
this.student = student;
}
}
@Component
public class Student { @Autowired
private School school; public School getSchool() {
return school;
} public void setSchool(School school) {
this.school = school;
}
}
public class APP {
public static void main(String[] args) throws InterruptedException {
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(Configurate.class);
School school =(School) applicationContext.getBean("school");
Student student =(Student) applicationContext.getBean("student");
System.out.println(school.getClass());//class com.aop.School
System.out.println(student.getClass());//class com.aop.Student
System.out.println(school.getStudent()==student);//false
System.out.println(school.getStudent().getClass());//class com.aop.Student$$EnhancerBySpringCGLIB$$834812b7 } }

底层源码:

跟到后面可以看到创建了cglib动态代理:

  


@lazy注解处理循环注入问题的更多相关文章

  1. Spring-Context的注解实现依赖注入功能

    使用Spring-Context的注解实现依赖注入功能. Demo要点: 本例子中主要使用Annotation功能来实现对MoviceService的注入.我们将Cinema.java的头部标注为@C ...

  2. SSM-Spring-07:Spring基于注解的di注入

    ------------吾亦无他,唯手熟尔,谦卑若愚,好学若饥------------- 注解: 说起注解,哇哦,每个人都或多或少的用到过 像什么@Overried,@Test,@Param等等之前就 ...

  3. spring下应用@Resource, @Autowired 和 @Inject注解进行依赖注入的差异

    为了探寻 '@Resource', '@Autowired', 和'@Inject'如何解决依赖注入中的问题,我创建了一个"Party"接口,和它的两个实现类"Perso ...

  4. 07 Spring框架 依赖注入(四)基于注解的依赖注入

    前面几节我们都在使用xml进行依赖的注入,但是在实际的开发中我们往往偏爱于使用注解进行依赖注入,因为这样更符合我们人的思维,并且更加快捷,本节就来讲述Spring基于注解的依赖注入: 信息注入注解 @ ...

  5. Spring 注解Autowired自动注入bean异常解决

      错误: org.springframework.beans.factory.NoSuchBeanDefinitionException: No bean named 'xx' is defined ...

  6. spring boot 中@Autowired注解无法自动注入的错误

    版权声明:本文为博主原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明. 本文链接:https://blog.csdn.net/huihuilovei/article/de ...

  7. 【Java】SpringBoot的bean懒加载@Lazy注解

    注解说明 @Lazy:一般情况下,Spring容器在启动时会创建所有的Bean对象,使用@Lazy注解可以将Bean对象的创建延迟到第一次使用Bean的时候. 引用 在类上加入@Lazy或者@Lazy ...

  8. 【Spring注解驱动开发】使用@Lazy注解实现懒加载

    写在前面 Spring在启动时,默认会将单实例bean进行实例化,并加载到Spring容器中.也就是说,单实例bean默认在Spring容器启动的时候创建对象,并将对象加载到Spring容器中.如果我 ...

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

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

随机推荐

  1. 必须添加对程序集"System.Core"的引用

    在项目下的web.config中添加 <compilation debug="true" targetFramework="4.0"> <as ...

  2. HTML5入门教程:响应式页面布局

    摘自:https://www.sohu.com/a/225633935_647584 随着互联网时代的发展,我们对网页布局有了新的要求,大气,美观,能够在不同的设备上呈现令人焕然一新的效果.此时,一个 ...

  3. iOS项目之WKWebView替换UIWebView相关

    在网上已经有了许多关于UIWebView替换为WKWebView的文章,所以在这里就不在多说替换的细节了,不会的可以在网上搜搜. 下面是我在项目中遇到的问题: 问题一:在UIWebView中,网页显示 ...

  4. windows升级node

    之前用的node版本太低,不兼容webpack4.x,需要升级,网上搜索了许多方法,发现在windows下行不通 找到的教程都说全局安装node下的一个名为n的模块,这个模块是node专门用于版本管理 ...

  5. HDU 6186 CS Course(前缀+后缀)

    http://acm.hdu.edu.cn/showproblem.php?pid=6186 题意:给出n个数,共有n次询问,每次询问给出一个数p,求除去第p个数后的n-1个数的&.|.^值. ...

  6. WebApi请求原理

    一.路由: 1.首先执行Application_start 2 .注册路由 WebApiConfig,把路由规则写入一个容器 运行 请求会去容器匹配-找到控制器容器 一般不指定Action, rest ...

  7. JVM运行时内存模型

    JDK1.7版本图 一,栈   基本数据类型的局部变量是直接保存在栈中. 栈帧:一个栈里面会包含多个栈帧,每一个栈帧代表一个方法的开始到结束,它涵盖了整个方法运行期间所有的操作和数据 栈帧 1:局部变 ...

  8. ado.net 批量添加 更新 删除

    自曾列就别往下看 别折腾了   使用 SqlBulkCopy ,dataTable 必须跟sql里面的表字段完全一样 下面在sqlserver中演示 mysql 请google MySqlBulkLo ...

  9. WPF InkCanvas 书写毛笔效果

    https://www.cnblogs.com/younShieh/p/10602787.html

  10. Python自学:第三章 使用列表中的各个值

    bicycles = ['trek','cannondale','redline','specialized'] message = "My first bicycle was a &quo ...