简体   繁体   English

Spring @Autowire与getBean(className)的性能

[英]Performance of Spring @Autowire vs getBean(className)

There are two variants of code: 有两种代码变体:

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();
}
}

Will there be any performance penalties in the first variant (by the way in the first place it's not spring bean, just simple class)? 第一个变体会不会有任何性能上的损失(首先不是简单的Spring bean,而是简单的类)? Does Autowiring do the same as getBean? 自动装配与getBean一样吗?

PS I think I should expand my question a little. 附言:我认为我应该扩大我的问题。 The situation is that team I joined uses Spring injection in the project only via getBean(className). 情况是,我加入的团队仅通过getBean(className)在项目中使用Spring注入。 The reason I guess is that most of project classes already written are not Spring beans and using autowiring in one class means usually making dependent class bean as well and so on until most of the classes become beans... 我猜想原因是大多数已编写的项目类都不是Spring Bean,并且在一个类中使用自动装配通常意味着也要制作从属类Bean,依此类推,直到大多数类成为Bean。

Ok, I think I understand testability penalties and overall lacking of code-style of such an approach. 好的,我认为我理解可测试性的惩罚,并且总体上缺乏这种方法的代码风格。 But isn't there a perfomance penalty alsо? 但是,是否没有性能惩罚als®? Isn't there difference between performance of ready-to-go Spring singleton that is constructed on startup with all it's fields autowired and invoking getBean(classname) (afaik several times slower then pure hashmap.get(object)) from non-spring non-singleton class (ecpecially in critical places)? 在启动时构建的具有自动连接的所有字段的即兴Spring Singleton的性能与从非Spring Non调用getBean(classname)(比纯hashmap.get(object)慢几倍的aBean)的性能之间没有区别-单班(特别是在关键地方)?

PSS I created smth like mini-benchmark (I understand that it's hard to get real info because of work of GC, JIT and so on but nevertheless...). PSS我创建了像迷你基准这样的工具(我知道由于GC,JIT等的工作很难获得真实的信息,但是……)。 My results are (the bigger numbers - the worse): Autowiring time - 193, GetBean time - 2161, Method in the same class - 173, Static method in another class - 206 我的结果是(数字越大-越差):自动装配时间-193,GetBean时间-2161,同一类中的方法-173,另一类中的静态方法-206

IMO, you shouldn't use any of this. IMO,您不应该使用任何这些。 As some users already mentionned in comments, you shouldn't take care of performances. 正如一些用户在评论中已经提到的那样,您不应该关注表演。 But for testability, use constructor based injection (and the @Autowired is implicit) : 但是为了可测试性,请使用基于构造函数的注入(并且@Autowired是隐式的):

@Component
public class MyClass {

  private final AnotherClass object;     

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

It's going to be inefficient to lookup a bean in the Spring context (which is often composite) every time you need to access it. 每次需要访问时,在Spring上下文(通常是复合的)中查找bean效率低下。 You're essentially looking up an item in multiple hash tables multiple times, thrashing the CPU cache, wasting time and potentially preventing other optimization like inlining due to a more complex execution path. 本质上,您需要多次在多个哈希表中查找项目,从而影响了CPU缓存,浪费了时间,并可能由于更复杂的执行路径而阻止其他优化(如内联)。

Definitely use autowiring (annotation-based or constructor-based). 绝对使用自动装配(基于注释或基于构造函数)。 That way the lookup is done once at application startup, and after that the class is accessed via a direct reference. 这样,查找在应用程序启动时完成一次,然后通过直接引用访问该类。

Testability is perfectly fine even with the @Autowired annotation. 即使使用@Autowired批注,可测试性也很好。 You simply autowire mocks instead of actual objects. 您只需自动装配模拟而不是实际对象即可。 Also look into Mockito and Spring-Test annotations to inject mocks and otherwise augment the Spring context for testing purposes. 还可以查看MockitoSpring-Test批注以注入模拟内容,或出于测试目的而扩展Spring上下文。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM