【问题标题】:Self reference in @Repository class result in circular reference@Repository 类中的自引用导致循环引用
【发布时间】:2021-03-03 10:16:03
【问题描述】:

我发现@Repository中的自引用不起作用,例如:

@Repository
public class HelloService {
    static final Logger Log = LoggerFactory.getLogger(HelloService.class);

    @Autowired
    HelloService self;  // <----- self reference
    ...
}

循环引用错误

o.s.b.w.s.c.AnnotationConfigServletWebServerApplicationContext - 上下文初始化期间遇到异常 - 取消刷新尝试:org.springframework.beans.factory.BeanCurrentlyInCreationException:创建名为“helloService”的bean时出错:名为“helloService”的bean已注入其他bean [helloService]在其原始版本中作为循环引用的一部分,但最终已被包装。这意味着所说的其他 bean 不使用 bean 的最终版本。这通常是过度渴望类型匹配的结果 - 例如,考虑使用 'getBeanNamesOfType' 并关闭 'allowEagerInit' 标志。

但是,当将 Repository 更改为 @Component@Service 时,此技巧可能会起作用。作为一种解决方法,我必须在self 中添加一个@Lazy

【问题讨论】:

  • 为什么有人要这样做?
  • 我们想使用self通过代理对象而不是目标对象来访问AOP方法。尽管这可能是一个不好的做法,但它是一个非常简单的解决方案。

标签: java spring


【解决方案1】:

HelloService 的行为取决于 Spring Data JPA 存储库的引导方式,在这种情况下,这似乎是默认模式:

  • DEFAULT(默认) — 存储库会立即实例化,除非使用 @Lazy 明确注释。

阅读日志,并查找此条目:

RepositoryConfigurationDelegate : Bootstrapping Spring Data JPA repositories in XYZ mode.

然后看看那个 XYZ 是什么。

@Lazy 可以帮助您,因为:

如果@Component 或@Bean 定义中不存在此注解,则会发生急切初始化。如果存在并设置为 true,则 @Bean 或 @Component 在被另一个 bean 引用或从封闭的 BeanFactory 显式检索之前不会被初始化。

为了了解您的其他组件是如何被初始化的,最好有日志、属性、配置或其他任何可能影响 Spring 应用程序行为的东西。如果你不提供minimal reproducible example

,真的很难猜到你有什么

其他要点:

一般来说,将A 注入A 是一种非常糟糕的做法,而且您几乎应该永远不要这样做。

但是,如果不是@Lazy bean A 被注入到自身中,那么你会得到一个异常也就不足为奇了。你需要在 Spring Container 中有一个现成的 bean,以便将它注入某个地方;而且,为了准备好那个 bean,Spring 必须注入它的依赖项.. 然而,在你的代码中:

@Repository
public class HelloService {
    static final Logger Log = LoggerFactory.getLogger(HelloService.class);

    @Autowired
    HelloService self;  // <----- self reference
    ...
}

这取决于它自己。

您要告诉应用程序上下文:

  1. 实例化 bean helloService(包括准备它,通过注入其每个依赖项);
  2. helloService bean 注入自身。

你认为不先完成step 1就可以完成step 2吗?如果step 2 无法完成,step 1 将如何完成?

您正在注入的东西尚未准备好,为了让它准备好,您需要注入它,它自己,同样,它还没有准备好。 ..等等..

这会让你陷入循环引用问题,这是一个死锁。

【讨论】:

  • 感谢您的回复。该项目是一个基于spring boot的web应用,不使用JPA。糟糕的是,我无法通过简单的演示重现该问题
  • 关于“其他点”部分,是的,这确实是一个循环引用问题,但Spring可以解决它(使用字段注入时)。作为证明,请改用@Component@Service,它可以工作,还没有问题。
  • 作为演示 Spring 可以解决这种循环引用(自引用)的演示,我们可以从这个项目开始 spring.io/guides/gs/spring-boot。将HelloServiceApplication类放在同一路径下,我们可以看到没有出现循环引用问题。
猜你喜欢
  • 1970-01-01
  • 2018-04-10
  • 2018-01-24
  • 1970-01-01
  • 1970-01-01
  • 2021-09-14
  • 2018-11-27
  • 1970-01-01
  • 2021-08-28
相关资源
最近更新 更多