@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. Cycle (KMP + hash)

    题意:给你2个串,让你判断2个字符串的前缀是否满足首尾连接形成的环是不是一样的. 思路:我们需要提前知道的是满足条件的前缀一定满足 strA = str1 + str2, strB = str2 + ...

  2. spring AOP自定义注解方式实现日志管理

    今天继续实现AOP,到这里我个人认为是最灵活,可扩展的方式了,就拿日志管理来说,用Spring AOP 自定义注解形式实现日志管理.废话不多说,直接开始!!! 关于配置我还是的再说一遍. 在appli ...

  3. mybatis常见问题和错误

    1. jdbc java type 映射关系 1) mysql的text 在mybatis中使用varchar类型 2. mybatis常见的错误 3.There is no getter for p ...

  4. Hdu2033 人见人爱A+B (贪心)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2033 人见人爱A+B Time Limit: 2000/1000 MS (Java/Others)   ...

  5. Vue 组件&组件之间的通信 之 template模板引用与动态组件的使用

    template模板引用 在component的template中书写大量的HTML元素很麻烦. Vue提供了<template>标签,可以在里边书写HTML,然后通过ID指定到组建内的t ...

  6. Docket 使用命令

    Docket 使用命令 查 # 查询当前可以下载的镜像 docker search httpd  |_ NAME:镜像仓库源的名称 |_ DESCRIPTION:镜像的描述 |_ OFFICIAL:是 ...

  7. Consul 常用指令

    Consul 常用指令 # 通告地址 -advertise # 集群节点之间通信地址 -bind # 设置服务器为bootstrap模式.在一个dc中只有一个server处于bootstrap模式.一 ...

  8. Linux 创建自定义命令

    Linux 创建自定义命令 Linux 可以创建自定义使用命令 这里我们采取使用“alias”命令.这里我们首先了解两个文件,通过这两个文件我们可以根据环境配置相应的自定义命令. 该文件内创建的自定义 ...

  9. StringUtils工具类常用方法汇总(判空、转换、移除、替换、反转)

    Apache commons lang3包下的StringUtils工具类中封装了一些字符串操作的方法,非常实用,使用起来也非常方便.最近自己也经常在项目中使用到了里面的一些方法,在这里将常用的方法总 ...

  10. 【问题解决:启动卡死】Eclipse启动卡死的解决办法

    问题描述 Eclipse启动后卡死 问题分析 由于上一次没有正确关闭,导致在启动的时候开始 问题解决 方法1(推荐): 到<workspace>\.metadata\.plugins\or ...