Spring循环依赖及@Lazy解决

您所在的位置:网站首页 lazy怎么记忆 Spring循环依赖及@Lazy解决

Spring循环依赖及@Lazy解决

2024-07-13 12:54| 来源: 网络整理| 查看: 265

背景

之前写了一个用自定义注解+切面进行日志和日常统一处理的方案,但是遇到了一个问题就是,如果注解标记的方法A 被同一个类中另一个方法B调用,当B方法被外部调用时,注解将不生效,切面无法拦截。即外部调用B方法时,注解@RpcCheck不会生效。

@RpcCheck public void A() { } public void B() { A(); }

当时查了一下解决原因,切面之所以会生效,是因为创建了代理对象,在调目标方法A之前,代理对象进行了增强处理(切面逻辑)。但是B调用A时,是类的内部方法调用,就不会再次创建代理对象,而是使用当前实例,所以也就不会进行增强处理了,即切面无法生效。

解决方案就是,在B调用A时,获取代理对象,使用代理对象调用。实现方式以下两种

//1. 使用AopContext.currentProxy()获取代理对象 public class UserService { public void B() { UserService userService = (UserService) AopContext.currentProxy(); userService.A(); } } //2. 自己注入自己, 即相当于外部直接调用A public class UserService { @Autowired private UserService thisService; public void B() { thisService.A(); } }

因为方法1需要强制类型转换,所以我果断选择了第二种,然后我就遇到了新问题。工程可以正常启动,但是我在写单测Mock方法的时候,会抛异常 circular reference (循环依赖),然后就进入了本篇正题......【从一个坑跳到另一个坑🐶】

Caused by: org.springframework.beans.factory.BeanCurrentlyInCreationException: Error creating bean with name '': Bean with name '' has been injected into other beans [] in its raw version as part of a circular reference, but has eventually been wrapped. This means that said other beans do not use the final version of the bean. This is often the result of over-eager type matching - consider using 'getBeanNamesOfType' with the 'allowEagerInit' flag turned off, for example.

循环依赖及解决

按照上面说的,在UserService[1号]里又注入了UserService[2号],SpringBean初始化的过程是,在初始化[1号]时发现其依赖[2号],那就先初始化[2号],结果又回到了要初始化[1号]。简单说,这不就是套娃.......没完没了🐶

解决方案呢,我是加了@Lazy注解,这个注解的作用是呢,延迟加载,只有真正是用的时候,才会去真正的初始化。上面说的

初始化[2号]时,会直接创建一个[2号]*,即代理对象,将代理对象注入到[1号]中,直接终止了套娃......当真正调用方法B,执行        thisService.A()时,才会创建[2号]。当然还有其他方案,但是我觉得没有延迟加载简洁,想了解可以看下面的文档。  

膜拜各位大佬

解决AOP切面在嵌套方法调用时不生效问题

spring Aop嵌套调用的解决办法

SpringBoot中的Bean懒加载————@Lazy

Spring如何解决循环依赖?

SpringBoot(6)— Bean懒加载@Lazy和循环依赖处理

@lazy注解处理循环注入问题



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3