Производительность Spring @Autowire против getBean (className) - PullRequest
0 голосов
/ 25 февраля 2019

Существует два варианта кода:

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, а простой класс)?Делает ли Autowiring то же самое, что и getBean?

PS Думаю, мне следует немного расширить свой вопрос.Ситуация такова, что команда, к которой я присоединился, использует Spring инъекцию в проекте только через getBean (className).Я полагаю, что причина в том, что большинство уже написанных классов проекта не являются bean-компонентами Spring, и использование автопроводки в одном классе означает, что обычно также делается bean-компонент зависимого класса и так далее, пока большинство классов не станут bean-компонентами ...

ХорошоЯ думаю, я понимаю штрафы за тестируемость и общее отсутствие стиля кода такого подхода.Но разве не существует штраф за исполнение?Нет ли разницы между производительностью готового к использованию синглтона Spring, созданного при запуске со всеми автоматически связанными его полями, и вызовом getBean (classname) (afaik в несколько раз медленнее, чем чистый hashmap.get (object)) из non-spring non-Singleton класс (особенно в критических местах)?

PSS Я создал что-то вроде мини-бенчмарка (я понимаю, что трудно получить реальную информацию из-за работы GC, JIT и так далее, но тем не менее ...),Мои результаты (чем больше цифр, тем хуже): время автопроводки - 193, время GetBean - 2161, метод в одном классе - 173, метод статический в другом классе - 206

Ответы [ 2 ]

0 голосов
/ 25 февраля 2019

Будет неэффективно искать бин в контексте Spring (который часто является составным) каждый раз, когда вам нужно получить к нему доступ.По сути, вы просматриваете элемент в нескольких хэш-таблицах несколько раз, перебирая кэш-память ЦП, тратя время и потенциально предотвращая другие оптимизации, такие как встраивание, из-за более сложного пути выполнения.

Определенно используйте автоматическое подключение (на основе аннотацийили на основе конструктора).Таким образом, поиск выполняется один раз при запуске приложения, и после этого доступ к классу осуществляется по прямой ссылке.

Тестируемость отлично работает даже с аннотацией @Autowired.Вы просто автоматически проводите макеты вместо реальных объектов.Также обратите внимание на аннотации Mockito и Spring-Test для внедрения макетов и иного дополнения контекста Spring для целей тестирования.

0 голосов
/ 25 февраля 2019

IMO, вы не должны использовать ничего из этого.Как уже упоминали некоторые пользователи в комментариях, вам не следует заботиться о выступлениях.Но для тестируемости используйте инъекцию на основе конструктора (а @Autowired неявно):

@Component
public class MyClass {

  private final AnotherClass object;     

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