如何使用 CDI 注入到 3rd 方实例化的对象中
How to use CDI to inject into an object instantiated by 3rd party
我有一个由第 3 方代码实例化的 class(它使用反射来创建对象。)我提供了他们接口的实现,他们创建了对象。在我的实现中,我想使用 CDI 来注入执行逻辑的服务。正确的做法是什么?
public interface ThirdPartyInterface {
public void DoSomething();
}
public class InjectedService {
public void DoSomeLogic() { ... }
}
public class MyImplementation implements ThirdPartyInterface {
@Inject InjectedService service;
@Override
public void DoSomething() {
service.DoSomeLogic();
}
}
我原本以为这可以通过 CDI 的魔力来实现,但发现我的服务对象为空。
到目前为止我唯一想到的就是在构造函数中手动注入服务
public MyImplementation() {
CDI<Object> cdi = CDI.current();
service = cdi.select(InjectedService.class).get();
}
这是correct/only/best获取实例的方式吗?我正在使用 Weld 进行 CDI 实施。
我还发现这在构造函数中有效:
public MyImplementation() {
CDI<Object> cdi = CDI.current();
BeanManager bm = cdi.getBeanManager();
AnnotatedType<MyImplementation> myType = bm.createAnnotatedType(MyImplementation.class);
Set<Bean<?>> beans = bm.getBeans(MyImplementation.class);
Bean<?> bean = bm.resolve(beans);
@SuppressWarnings("unchecked")
CreationalContext<MyImplementation> cc = (CreationalContext<MyImplementation>)bm.createCreationalContext(bean);
bm.createInjectionTarget(myType).inject(this, cc);
}
只要有人手动创建对象,CDI 默认情况下不会向其中注入任何内容。
您使用构造函数注入的方法可能会奏效,除非您进入 EAR 等 CDI.current()
可能无法达到您的预期。
有一种方法可以让 CDI 注入到手动创建的对象中——第 3 方必须执行此步骤才能使其工作。您需要 BeanManager
和一个要注入的实例:
BeanManager beanManager = ...; // get hold of bean manager, can be injected
CreationalContext<Object> ctx = beanManager.createCreationalContext(null);
@SuppressWarnings("unchecked")
InjectionTarget<MyImplementation> injectionTarget = (InjectionTarget<MyImplementation>) beanManager
.getInjectionTargetFactory(beanManager.createAnnotatedType(myImplementationInstance.getClass())).createInjectionTarget(null);
injectionTarget.inject(myImplementationInstance, ctx);
注意 - 执行此操作后,您将负责在不再需要对象后进行清理。将 CreationContext
存储在某处并对其调用 release()
方法以便正确处理它(包括所有可能的销毁前调用等)。
或者,既然您已经在使用 CDI,为什么第 3 方不直接 @Inject
您提供的 bean?
我有一个由第 3 方代码实例化的 class(它使用反射来创建对象。)我提供了他们接口的实现,他们创建了对象。在我的实现中,我想使用 CDI 来注入执行逻辑的服务。正确的做法是什么?
public interface ThirdPartyInterface {
public void DoSomething();
}
public class InjectedService {
public void DoSomeLogic() { ... }
}
public class MyImplementation implements ThirdPartyInterface {
@Inject InjectedService service;
@Override
public void DoSomething() {
service.DoSomeLogic();
}
}
我原本以为这可以通过 CDI 的魔力来实现,但发现我的服务对象为空。
到目前为止我唯一想到的就是在构造函数中手动注入服务
public MyImplementation() {
CDI<Object> cdi = CDI.current();
service = cdi.select(InjectedService.class).get();
}
这是correct/only/best获取实例的方式吗?我正在使用 Weld 进行 CDI 实施。
我还发现这在构造函数中有效:
public MyImplementation() {
CDI<Object> cdi = CDI.current();
BeanManager bm = cdi.getBeanManager();
AnnotatedType<MyImplementation> myType = bm.createAnnotatedType(MyImplementation.class);
Set<Bean<?>> beans = bm.getBeans(MyImplementation.class);
Bean<?> bean = bm.resolve(beans);
@SuppressWarnings("unchecked")
CreationalContext<MyImplementation> cc = (CreationalContext<MyImplementation>)bm.createCreationalContext(bean);
bm.createInjectionTarget(myType).inject(this, cc);
}
只要有人手动创建对象,CDI 默认情况下不会向其中注入任何内容。
您使用构造函数注入的方法可能会奏效,除非您进入 EAR 等 CDI.current()
可能无法达到您的预期。
有一种方法可以让 CDI 注入到手动创建的对象中——第 3 方必须执行此步骤才能使其工作。您需要 BeanManager
和一个要注入的实例:
BeanManager beanManager = ...; // get hold of bean manager, can be injected
CreationalContext<Object> ctx = beanManager.createCreationalContext(null);
@SuppressWarnings("unchecked")
InjectionTarget<MyImplementation> injectionTarget = (InjectionTarget<MyImplementation>) beanManager
.getInjectionTargetFactory(beanManager.createAnnotatedType(myImplementationInstance.getClass())).createInjectionTarget(null);
injectionTarget.inject(myImplementationInstance, ctx);
注意 - 执行此操作后,您将负责在不再需要对象后进行清理。将 CreationContext
存储在某处并对其调用 release()
方法以便正确处理它(包括所有可能的销毁前调用等)。
或者,既然您已经在使用 CDI,为什么第 3 方不直接 @Inject
您提供的 bean?