Spring循环依赖及@Lazy解决

17 篇文章 0 订阅

背景

之前写了一个用自定义注解+切面进行日志和日常统一处理的方案,但是遇到了一个问题就是,如果注解标记的方法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注解处理循环注入问题

  • 5
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值