Я понял, что существует два общих способа получения автоматически созданного экземпляра bean, управляемого CDI, через BeanManager
, когда имеется только один Bean<T>
для начала (созданный на основе Class<T>
):
-
BeanManager#getReference()
, что чаще всего показано в сниппеты:Bean<TestBean> bean = (Bean<TestBean>) beanManager.resolve(beanManager.getBeans(TestBean.class)); TestBean testBean1 = (TestBean) beanManager.getReference(bean, bean.getBeanClass(), beanManager.createCreationalContext(bean));
-
Context#get()
, который менее часто отображается в фрагментах:Bean<TestBean> bean = (Bean<TestBean>) beanManager.resolve(beanManager.getBeans(TestBean.class)); TestBean testBean2 = beanManager.getContext(bean.getScope()).get(bean, beanManager.createCreationalContext(bean));
В эффектах они в конечном итоге выполняют одно и то же: возвращая проксированную ссылку на текущий управляемый CDI bean экземпляр и автоматически создает экземпляр bean, если он еще не существует в области.
Но они делают это несколько иначе: BeanManager#getReference()
всегда создает целый новый экземпляр прокси, а Context#get()
повторно использует существующий экземпляр прокси, если он уже создан ранее. Это очевидно, когда вышеуказанный код выполняется в методе действий существующего экземпляра TestBean
:
System.out.println(testBean1 == testBean2); // false
System.out.println(testBean1 == this); // false
System.out.println(testBean2 == this); // true
javadoc из Context#get()
очень явственно в этом:
Верните существующий экземпляр определенного контекстного типа или создайте новый экземпляр, вызвав Contextual.create(CreationalContext) и верните новый экземпляр.
в то время как javadoc BeanManager#getReference()
недостаточно явствует по этому поводу:
Получает контекстную ссылку для определенного bean и определенного типа bean bean.
Это меня смутило. Когда вы используете тот или иной? Для обоих способов вам нужен экземпляр Bean<T>
в любом случае, из которого легко доступны область bean и bean, которая требуется в качестве дополнительного аргумента. Я не могу представить, почему в этом конкретном случае они должны быть поставлены снаружи.
Я могу себе представить, что Context#get()
более эффективен с точки зрения памяти, так как он без необходимости создает другой экземпляр прокси, ссылающийся на тот же самый базовый экземпляр bean, но просто находит и повторно использует существующий экземпляр прокси.
Это ставит меня на следующий вопрос: когда именно BeanManager#getReference()
более полезно, чем Context#get()
? Он чаще всего проявляется в фрагментах и чаще всего рекомендуется в качестве решения, но он только излишне создает новый прокси-сервер, даже если он уже существует.