@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. 设置vim支持gbk

    linux下的默认字符集是utf-8,但Windows下默认是GBK,如果我们在linux下打开Windows中的文件就很容乱码,可以通过下面的设置使vim支持GBK编码. 首先,确认你的系统中安装了 ...

  2. solr简单搜索案例

    solr简单搜索案例 使用Solr实现电商网站中商品信息搜索功能,可以根据关键字搜索商品信息,根据商品分类.价格过滤搜索结果,也可以根据价格进行排序,实现分页. 架构分为: 1. solr服务器 2. ...

  3. oracle数据库调整字段顺序

    oracle数据库调整字段顺序 https://blog.csdn.net/xiaobaixie/article/details/77892034

  4. RabbitMQ详解(三)------RabbitMQ的五种模式

    RabbitMQ详解(三)------RabbitMQ的五种模式 1.简单队列(模式) 上一篇文章末尾的实例给出的代码就是简单模式. 一个生产者对应一个消费者!!! pom.xml ​ 必须导入Rab ...

  5. Linux下执行Oracle的sql脚本

    (1)  启动监听: Root用户登录后,输入: $su – oracle 回车(Oracle为Oracle数据库安装用户,必须有横杠: - ) 启动监听: $lsnrctl start --启动 $ ...

  6. 复旦大学2017--2018学年第一学期(17级)高等代数I期末考试第六大题解答

    六.(本题10分)  设 $M_n(K)$ 为数域 $K$ 上的 $n$ 阶方阵全体构成的线性空间, $A,B\in M_n(K)$, $M_n(K)$ 上的线性变换 $\varphi$ 定义为 $\ ...

  7. Git的初次使用

    一.配置本地Git库 1.下载安装好Git,并配置自己的信息. git config --global user.name"yourname"配置你的名称 git config - ...

  8. 进程池 和 multiprocessing.Pool模块

    进程池的概念 在程序实际处理问题过程中,忙时会有成千上万的任务需要被执行,闲时可能只有零星任务.那么在成千上万个任务需要被执行的时候,我们就需要去创建成千上万个进程么?首先,创建进程需要消耗时间,销毁 ...

  9. FZOJ P2109 【卡德加的兔子】

    题目描述 卡德加喜欢养兔子.他在达拉然的下水道里放了 $N$ 个兔笼(编号从 $1$ 到 $N$),里面养着他从德拉诺带来的兔子.它们的繁殖遵循斐波那契数列的规律:刚开始时,笼子里有一对刚出生的兔子. ...

  10. Bioconductor软件安装与升级

    1 安装工具Bioc的软件包不能使用直接install.packages函数,它有自己的安装工具,使用下面的代码: source("https://bioconductor.org/bioc ...