zoukankan      html  css  js  c++  java
  • @lazy注解处理循环注入问题

    
    

    @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动态代理:

      




  • 相关阅读:
    Java Json 数据下划线与驼峰格式进行相互转换
    Java反射常用示例
    ApplicationContextAware 快速获取bean
    Spring AOP自动代理创建者
    Spring依赖检查
    Bean作用域实例
    注入值到Spring bean属性
    用javaConfig 代替 xml 配置
    spring使用@Autowired装载
    Spring 概述
  • 原文地址:https://www.cnblogs.com/yangxiaohui227/p/10523025.html
Copyright © 2011-2022 走看看