【问题标题】:Performance of Spring @Autowire vs getBean(className)Spring @Autowire 与 getBean(className) 的性能
【发布时间】:2019-02-25 15:24:45
【问题描述】:

代码有两种变体:

public class MyClass {
 public void myMethod() {
  AnotherClass object = SpringContexHolder.getContext().getBean(AnotherClass.class);
  object.doSomething();
 }
}

@Component
public class MyClass {
@Autowired
AnotherClass object;     

public void myMethod() {
 object.doSomething();
}
}

在第一个变体中会有任何性能损失(顺便说一下,首先它不是 spring bean,只是简单的类)? 自动装配和 getBean 一样吗?

附:我想我应该稍微扩展一下我的问题。情况是我加入的团队只通过getBean(className)在项目中使用Spring注入。我猜的原因是大多数已经编写的项目类都不是 Spring bean,并且在一个类中使用自动装配意味着通常也会使依赖类 bean 等等,直到大多数类变成 bean...

好的,我想我理解这种方法的可测试性惩罚和整体缺乏代码风格。但是难道没有性能惩罚吗?在启动时构建的即用型 Spring 单例的性能是否存在差异,它的所有字段都是自动装配的,并且从非 Spring 非- 单例类(特别是在关键地方)?

附言我创建了类似 mini-benchmark 的东西(我知道由于 GC、JIT 等的工作,很难获得真实的信息,但尽管如此......)。 我的结果是(数字越大 - 越差): 自动装配时间 - 193,GetBean 时间 - 2161,同一个类中的方法 - 173,另一个类中的静态方法 - 206

【问题讨论】:

  • 始终使用第二种方式进行可读性和测试。同样,只有在没有找到 bean 时调用 myMethod 时,第一种方法才会失败,而第二种方法甚至不会让您的应用程序正常启动
  • 另外,你不应该真正关心 spring 的性能,因为它本身已经有相当大的开销,并且可能不会用于性能关键的应用程序
  • IMO,您不应该真正关心启动时应用程序的性能。您使用 autowired 是因为它更方便;如果您关心启动时间,那么您可以完全避免使用 Spring,但缺点是您需要手动完成所有操作。
  • 我不认为'使用弹簧'相对于'你不应该真正关心性能'。这个问题基于使用spring,getBean@autowired之间的性能。我认为有两个概念“依赖查找”和“依赖注入”。 getBean 是依赖查找。 @autowired 是依赖注入。这个问题很好。

标签: java spring performance autowired


【解决方案1】:

每次需要访问时在 Spring 上下文(通常是复合的)中查找 bean 的效率会很低。您实际上是在多次查找多个哈希表中的一个项目,这会破坏 CPU 缓存,浪费时间,并且由于执行路径更复杂,可能会阻止其他优化,例如内联。

一定要使用自动装配(基于注解或基于构造函数)。这样,在应用程序启动时进行一次查找,然后通过直接引用访问该类。

即使使用@Autowired 注释,可测试性也非常好。您只需自动装配模拟而不是实际对象。还可以查看 MockitoSpring-Test 注释以注入模拟并以其他方式扩充 Spring 上下文以进行测试。

【讨论】:

  • Spring-Test 实际上是用于集成测试的,用它做单元测试真的很痛苦。使用构造函数注入对象允许您通过注入模拟(例如来自模拟)来进行单元测试,而无需所有弹簧样板。
  • 在禁用类路径扫描并为所有依赖项提供模拟时,我通常对 Spring-mock 没有任何问题。但 Mockito 也绝对有用。
【解决方案2】:

IMO,你不应该使用这些。正如一些用户在 cmets 中已经提到的那样,您不应该关心性能。但是为了可测试性,使用基于构造函数的注入(@Autowired 是隐式的):

@Component
public class MyClass {

  private final AnotherClass object;     

  public MyClass(AnotherClass object) {
    this.object = object;
  }
}

【讨论】:

    猜你喜欢
    • 2016-02-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-07-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多