在CDI 1.1中以编程方式查找/创建(非托管)bean

时间:2015-08-14 15:45:55

标签: cdi java-ee-7

我目前正在将库升级到JavaEE 7,我对如何查找和创建(非托管)bean实例有一些疑问。我在这里和互联网上查看了其他一些问题,发现了完全不同的解决方案。我在我的例子中忽略了限定符。

在库的旧实现(对于CDI 1.0)中,我只使用 Lookup#1 - 即使是@Dependent。

查找#1 :使用BeanManager的旧方式#getBeans()

public static <T> T getBean(Class<T> clazz) {
    Bean<T> bean = (Bean<T>) _beanManager.resolve(_beanManager.getBeans(clazz));
    if(bean.getScope().equals(Dependent.class)) {
        throw new IllegalArgumentException("Cdi#getBean(Class) should only be invoked for classes that do not belong to the "
                + "@Dependent scope");
    }
    CreationalContext<T> ctx = _beanManager.createCreationalContext(bean);
    return (T) _beanManager.getReference(bean, clazz, ctx);
}

我添加了if语句,因为我在其他地方读过,不应该以这种方式创建@Dependent范围的bean(没有明确定义的生命周期)。

查找#2 :CDI-1.1-way

public static <T> T getBean(Class<T> clazz) {
    return CDI.current().select(clazz).get();
}

Q1 :在CDI 1.1中应首选哪一个(#1或#2)来执行托管bean的编程查找?有什么优点和缺点?还有其他解决方案吗?

依赖/创建#1 :使用Unmanged和UnmanangedInstance

public static <T> UnmanagedInstance<T> getDependentBean(Class<T> clazz) {
    return new Unmanaged<>(clazz).newInstance();
}

UnmanagedInstance可以包含在DependentProvider类中,该类在构造函数中调用produce()inject()postConstruct(),在destroy方法中调用preDestroy()dispose() (为了进一步简化使用)。

依赖/创造#2 :受DeltaSpike的启发

public static <T> DependentProvider<T> getDependentBean(Class<T> clazz) {
    Bean<T> bean = (Bean<T>) _beanManager.resolve(_beanManager.getBeans(clazz));
    CreationalContext<T> ctx = _beanManager.createCreationalContext(bean);
    T instance = (T) _beanManager.getReference(bean, clazz, ctx);
    return new DependentProvider<T>(bean, ctx, instance);
}

返回的提供程序使用destroy()方法删除创建的实例。

public void destroy() {
    bean.destroy(instance, creationalContext);
}

我在DeltaSpike的实现中缺少的是对creationalContext.release()的调用。这不是必需的吗?

创建#3 :Instance =&gt;只能在托管bean中使用

@ViewScoped
class X implements Serializable {
    @Inject Instance<MyObject> _myObjectProvider;

    public void doSomething() {
        MyObject obj = _myObjectProvider.get();
        // ... work with obj

        // call _myObjectProvider.destroy(obj) as soon as we're done with the instance of MyObject.
    }
}

Q2 :同样,对于非托管“bean”的编程创建,应该首选哪一个(#1或#2,#3)?有什么优点和缺点?还有其他解决方案吗?

最后,我有一个关于如何检查bean是否已经实例化(例如会话范围的bean)的问题。我提出了以下方法(仅适用于非@Dependent):

public <T> boolean existsBeanInstance(String name) {
    Bean<T> bean = (Bean<T>) _beanManager.resolve(_beanManager.getBeans(name));
    Context beanScopeContext = _beanManager.getContext(bean.getScope());
    return beanScopeContext.get(bean) != null;
}

Q3 :这可靠吗?

0 个答案:

没有答案