我寻找的是干净的CDI解决方案,而不是WELD依赖的解决方案,但到目前为止没有任何解决方法...
我需要测试使用@Inject @Any MyInterface bean获得的对象列表中的每个元素是否都是代理,并且当为true时,我需要获取真实的对象进行自省并获取该对象的所有属性。
我的WELD实施:
MyInterface interf = obj;
if (isProxy(interf )) {
interf = (RdxConfig) ((TargetInstanceProxy)interf ).getTargetInstance();
}
isProxy在何处定义(CDI解决方案?):
public boolean isProxy(Object obj) {
try{
return Class.forName("org.jboss.weld.bean.proxy.ProxyObject").isInstance(obj);
} catch (Exception e) {
LOGGER.error("Unable to check if object is proxy", e);
}
return false;
}
任何建议/适应症。在官方文档中,我没有提到内省(here)
然后我想用这样的东西来获取bean的所有属性:
Arrays.stream(interf.getClass().getDeclaredFields()).forEach(
field -> extractStuff(...)
);
我们使用Wildfly和WELD,但不想将我们绑定到CDI的实现。 预先感谢!
编辑: 问题更确切地说是:您是否知道一个干净的CDI解决方案,即WELD已已经使用 TargetInstanceProxy 实现了?如果我需要重返校园,或者我了解自己在写什么,就不用了。谢谢您抽出宝贵的时间来帮助您!
答案 0 :(得分:7)
CDI故意隐藏(或不公开)内部结构,因为在针对接口进行编程时,它们对于最终用户而言并不重要。此外,由于应始终 调用方法,将其弄乱可能会导致奇怪的错误通过代理而不是实际实例。
所以简短的答案是-不,没有纯CDI方法可以做到这一点。 (至少不是预期的。)
但是,看到您已经在使用Weld,还有其他方法。除了TomEE,Weld几乎与任何其他EE服务器一起提供,因此依赖Weld API应该非常安全。
现在,为什么要这么说-在Weld 3.x(WildFly 12+)中,API扩展为包含WeldConstruct
和WeldClientProxy
,它们是由Weld子激光器(拦截器/装饰器)和/或客户端代理-有关更多信息,请参见这些类的javadocs。
因此,如果必须执行此操作,则可以这样添加对Weld API的依赖关系:
<dependency>
<groupId>org.jboss.weld</groupId>
<artifactId>weld-api</artifactId>
<version>x.y.z</version>
</dependency>
然后,在您的代码中,您可以执行以下操作来检查注入的对象是否是代理:
@Inject
Foo foo;
public void doSomething() {
if (foo instanceof WeldClientProxy) {
// foo is a proxy
} else {
// not a proxy
}
}
如果要获取实际的实例,可以从WeldClientProxy
allows you to obtain Metadata
到retrieve the underlying contextual instance。那是我能带给您的最接近的信息。
答案 1 :(得分:2)
我不建议从cdi bean中公开内部实例,否则您将无法确定范围并可能产生奇怪的行为。
但是一般的做法是从cdi bean中return this
。
例如
interface Unwrapable<T> { T unwrap(); }
@ApplicationScoped
class Foo implements Unwrapable<Foo> {
public Foo unwrap() { return this; } // Will return the internal instance not the proxy
}
答案 2 :(得分:0)
一个常见的选择是1.获取要解开的实例的Bean,2.获取其作用域(bean.getScope()),3.从Bean管理器(可注入)获取与该作用域关联的Context ,4.如果在CDI上下文中可用,请执行context.get(bean)来获取未包装的实例(在某些情况下,您根本无法获得它)。