【问题标题】:Detecting unused Spring beans检测未使用的 Spring bean
【发布时间】:2016-03-16 22:51:10
【问题描述】:

给定一个专门包含急切(非惰性)单例 bean 的 Spring 配置,即默认值,如果没有在任何地方注入任何这些 bean,是否可以让 Spring 抛出异常?我本质上是在寻找一种方法来检测 Spring bean 形式的死代码。

我的问题和这些有点相似。

然而,

  • 我对手动检查图表或解析日志数据不感兴趣。
  • 我没有增加多个上下文文件、覆盖 bean、bean 后处理或 xml 的复杂性。这是一个简单、直接、注释驱动的配置。
  • 我使用的是 Spring Boot 1.2.6,它比这些问题更新了几年(可能存在新功能)。

如果缺少必要的 bean,Spring 肯定会抛出异常。是否也可以在找到 bean 但不必要的相反场景中抛出异常?

【问题讨论】:

  • 两种“快速”检测它们的方法,但它有点脏:1) 使用来自visualvm.github.io 的可视 VM,运行您的应用程序并查看所有 bean 的实例数。 2)声明私有所有bean(临时)以检查谁真正在调用它们(调用者也会出错)。仅当呼叫者抱怨时,才将您的 bean 类一一重新公开。最后仍然是私有的是未使用的。
  • 在IDEA中你也可以按Ctrl+鼠标左键单击它会显示你的bean(类)的所有用法
  • 自我注意:另一个不使用 Spring 或任何依赖反射的东西的原因。坚持使用 java 编译器。
  • @SridharSarnobat,您可能对Micronaut 感兴趣。

标签: java spring-boot spring-bean dead-code


【解决方案1】:

如果有必要的 bean,Spring 肯定会抛出异常 失踪。它也可以在相反的情况下抛出异常吗 找到了一个 bean 但没必要?

TL/DR

Spring 不支持这个(而且可能永远不会)。

加长版:

检测一个 bean 是否被使用真的很难。

首先,让我们定义 spring 什么时候抛出“missing bean”异常。

在 spring 上下文的初始化期间,spring 按照允许满足所有依赖项的顺序创建 bean(如果可能的话)。如果 bean 缺少依赖项,spring 将抛出异常(如您所说)。 所以,在spring上下文初始化过程中会抛出异常。

现在,您可以说我们可以监视此过程并查找未在任何其他 bean 中用作依赖项的 bean。 问题是并不是所有的bean依赖都是在spring上下文初始化过程中定义的。

我们看下面的例子:

首先,我们有一个简单的界面,DataService

public interface DataService {
 String getData();
}

现在我们有 2 个 spring bean 实现了这个接口:

@Service("firstDataService")
public class FirstDataService implements DataService {

  @Override
  public String getData() {
    return "FIRST DATA SERVICE";
  }
}

@Service("secondDataService")
public class SecondDataService implements DataService {
  @Override
  public String getData() {
    return "SECOND DATA SERVICE";
  }
}

现在,假设没有 bean 直接依赖于这两个 bean。当我直接说的时候,我的意思是没有任何 bean 通过 constructor-basedsetter-basedfield-based 依赖注入依赖于这些 bean。

因此,在 上下文初始化 过程中,spring 不会将这些 bean 注入到任何其他 bean 中。

现在,考虑以下 bean:

@Service
public class DataCollector {

  @Autowired
  ApplicationContext applicationContext;


  String getDataFromService(String beanName) {
    DataService ds = (DataService) applicationContext.getBean(beanName);
    return ds.getData();
  }
}

如果我使用beanName 参数的“firstDataService”值调用DataCollector bean 的getDataFromService 方法,该方法将返回“FIRST DATA SERVICE”作为结果。 如果我用“secondDataService”调用该方法,我将返回“SECOND DATA SERVICE”作为结果。

现在,当 spring 在上下文初始化期间查看 DataController 的定义时,无法确定 DataCollector 依赖于哪些 bean。 这完全取决于应用程序逻辑,以及我们在调用getDataFromService 方法时用于beanName 参数的值。

因此,spring 无法确定是否存在从未使用过的 bean(因为 bean 的使用可以是动态的,就像上面的情况一样)。

【讨论】:

  • 为了更清楚地了解我的设置,我尝试将其定义为最简单、最常见的场景。我希望检测没有注入任何这些bean:关键字被injected。我了解Service Locator anti-pattern,如上一个代码示例所示,是一个不同的野兽。对于我的设置来说,纯依赖注入的解决方案就足够了。
  • @jaco0646 抱歉回复晚了。我明白你的意思,但据我所知,目前春天没有这样的功能。我相信这样的功能可能会混淆用户并导致他们以错误的方式使用它。无论如何,如果你有兴趣实现类似的东西,你应该看看管理 bean 的 DI 的 DepedencyDescriptor 类(在这里你可以看到正在注入哪些 bean)和包含 bean 的 DefaultListableBeanFactory在容器中创建。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-07-18
  • 2022-01-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多