Инъекция @EJB против поиска - проблема производительности
У меня есть вопрос, связанный с возможной проблемой производительности при использовании аннотации @EJB. Представьте себе следующий сценарий
public class MyBean1 implements MyBean1Remote{
@EJB
private MyBean2Remote myBean2;
@EJB
private MyBean2Remote myBean3;
...
@EJB
private MyBean20Remote myBean20;
}
Существует компонент с большим количеством зависимостей от других компонентов. Согласно спецификации EJB, если я хотел бы внедрить MyBean1Remote в какой-либо другой компонент, контейнер должен был бы взять все необходимые зависимости из своего пула, вставить его в MyBean1Remote и затем вставить ссылку на заглушку MyBean1Remote.
поэтому в следующем сценарии контейнер должен зарезервировать 20 ejbs (myBean1 и его 19 зависимостей)
public class MyAnotherBean implement MyAnotherRemote{
@EJB
private MyBean1Remote myBean1
}
Допустим, в большинстве случаев мы будем использовать только одну зависимость для каждого бизнес-метода myBean1. В результате каждый раз, когда мы хотим внедрить этот компонент, мы заставляем контейнер резервировать множество ненужных EJB-компонентов. Предположим также, что мы работаем с удаленными bean-компонентами, поэтому, вероятно, контейнеру также потребуется выполнить некоторый алгоритм балансировки нагрузки перед внедрением зависимых bean-компонентов.
Вопросы:
Не приведет ли это к ненужному резервированию ресурсов и более к проблеме производительности при работе в кластерной среде?
Может быть, старый добрый ServiceLocator может быть лучшим решением, потому что при таком подходе мы будем запрашивать конкретный EJB, когда он нам действительно нужен?
2 ответа
Контейнер не внедряет экземпляр EJB; он внедряет экземпляр облегченного сгенерированного контейнером прокси-объекта, который реализует желаемый интерфейс.
public class MyBean1 implements MyBean1Remote {
...
}
public class MyAnotherBean implement MyAnotherRemote {
@EJB
private MyBean1Remote myBean1;
}
В вашем примере MyAnotherBean.myBean1 будет внедрен с прокси-объектом, который реализует интерфейс MyBean1Remote.
Если предположить, что сессионный компонент без сохранения состояния (поскольку вы упоминаете пул), контейнер не выделяет фактический экземпляр EJB из пула готовности метода, пока метод не будет вызван на прокси-сервере, и экземпляр не будет возвращен в пул до возврата вызова метода прокси,
В большинстве случаев и особенно при использовании сессионных компонентов без сохранения состояния ваши экземпляры будут объединены. Одно из оснований для объединения в пул заключается в том, что поиск внедрения зависимостей может быть относительно дорогим, поэтому bean-компонент объединяется (заглушки для) со всеми его зависимостями, уже внедренными.
Поэтому каждый раз, когда вы вызываете метод MyAnotherBean
Этот bean-компонент с 20 транзитивными зависимостями не создается, поскольку все эти зависимости решаются на лету. Вместо этого из пула выбирается полностью созданный экземпляр, и вызов метода направляется на это.
Также обратите внимание, что если вы не выполняете федерацию JNDI, вы обычно не можете легко внедрить удаленные EJB-компоненты.