Spring @Autowire与getBean(className)的性能

时间:2019-02-25 15:24:46

标签: java spring performance autowired

有两种代码变体:

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类,而是简单的类)? 自动装配与getBean一样吗?

P.S。我想我应该扩大我的问题。情况是,我加入的团队仅通过getBean(className)在项目中使用Spring注入。我猜想原因是大多数已编写的项目类都不是Spring Bean,并且在一个类中使用自动装配通常意味着也要制作依赖类Bean,依此类推,直到大多数类成为Bean ...

好吧,我想我了解可测试性的惩罚以及这种方法的整体代码风格的缺失。但是,是否没有性能惩罚als®?在启动时构建的具有自动连接的所有字段的即兴Spring Singleton的性能与从非Spring Non中调用getBean(classname)(比纯hashmap.get(object)慢几倍)之间的性能之间没有区别-单班(特别是在关键地方)?

P.S.S。我创建了像迷你基准之类的东西(我知道由于GC,JIT等的工作很难获得真实的信息,但是……)。 我的结果是(数字越大-越差): 自动装配时间-193,GetBean时间-2161,同一类中的方法-173,另一类中的静态方法-206

3 个答案:

答案 0 :(得分:1)

IMO,您不应使用其中任何一种。正如一些用户在评论中已经提到的那样,您不应该关注表演。但是为了可测试性,请使用基于构造函数的注入(并且@Autowired是隐式的):

@Component
public class MyClass {

  private final AnotherClass object;     

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

答案 1 :(得分:0)

我同意Oreste Viron尝试使用基于构造函数的注入。 但是关于你的问题。没有性能损失。

答案 2 :(得分:0)

每次需要访问它时,在Spring上下文(通常是复合的)中查找bean效率低下。本质上,您需要多次在多个哈希表中查找项目,从而浪费了CPU缓存,浪费了时间,并可能由于更复杂的执行路径而阻止其他优化(如内联)。

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

即使使用@Autowired批注,可测试性也很好。您只需自动装配模拟而不是实际对象即可。另外,请查看MockitoSpring-Test批注以注入模拟内容,或出于测试目的扩展Spring上下文。