从 CDI Proxy 获取真实对象
Get the real object from CDI Proxy
我在寻找一种干净的 CDI 解决方案,而不是依赖于 WELD 的解决方案,但到目前为止还没有...
我需要测试通过 @Inject
@Any
MyInterface
beans 获得的对象列表中的每个元素是否都是代理,以及何时 true
我需要获取真正的对象做内省,获取对象的所有属性。
我的 WELD 实现:
MyInterface interf = obj;
if (isProxy(interf )) {
interf = (Config) ((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 的实现。
提前致谢!
编辑:
更准确地说,问题是:您是否知道 WELD 已经 使用 TargetInstanceProxy 实施的干净 CDI 解决方案?如果我需要回学校或者我明白我在写什么,就不会。感谢您花时间提供帮助!
CDI 有意隐藏(或者更确切地说不暴露)内部结构,因为在针对 interface.Furthermore 进行编程时,它们对最终用户来说应该不重要,搞乱它会导致奇怪的错误,而你应该 总是 通过代理调用方法,而不是实际实例。
所以简短的回答是 - 不,没有纯粹的 CDI 方式来做到这一点。
(至少不是有意的。)
不过,看你已经在用Weld了,还有其他方法。 Weld 几乎随附了除 TomEE 之外的任何 EE 服务器,因此取决于 Weld API 应该是非常安全的。
现在我为什么要这么说 - 在 Weld 3.x(WildFly 12+)中,API 被扩展为包含 WeldConstruct
and WeldClientProxy
,它们是由 Weld 子类(interceptors/decorators)实现的接口and/or 客户端代理 - 请参阅那些 类 的 javadoc 了解更多信息。
所以如果你必须这样做,那么你可以像这样添加对 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
from which you can the retrieve the underlying contextual instance。这是我能让你最接近你所追求的。
一个常见的选择是:
- 获取要解包的实例的 Bean
- 获取其范围 (
bean.getScope()
)
- 从 bean 管理器(可注入)获取与范围关联的上下文
- 如果在 CDI 上下文中可用,请执行
context.get(bean)
以获取未包装的实例(在某些情况下您根本无法获取它)。
我在寻找一种干净的 CDI 解决方案,而不是依赖于 WELD 的解决方案,但到目前为止还没有...
我需要测试通过 @Inject
@Any
MyInterface
beans 获得的对象列表中的每个元素是否都是代理,以及何时 true
我需要获取真正的对象做内省,获取对象的所有属性。
我的 WELD 实现:
MyInterface interf = obj;
if (isProxy(interf )) {
interf = (Config) ((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 的实现。 提前致谢!
编辑: 更准确地说,问题是:您是否知道 WELD 已经 使用 TargetInstanceProxy 实施的干净 CDI 解决方案?如果我需要回学校或者我明白我在写什么,就不会。感谢您花时间提供帮助!
CDI 有意隐藏(或者更确切地说不暴露)内部结构,因为在针对 interface.Furthermore 进行编程时,它们对最终用户来说应该不重要,搞乱它会导致奇怪的错误,而你应该 总是 通过代理调用方法,而不是实际实例。
所以简短的回答是 - 不,没有纯粹的 CDI 方式来做到这一点。 (至少不是有意的。)
不过,看你已经在用Weld了,还有其他方法。 Weld 几乎随附了除 TomEE 之外的任何 EE 服务器,因此取决于 Weld API 应该是非常安全的。
现在我为什么要这么说 - 在 Weld 3.x(WildFly 12+)中,API 被扩展为包含 WeldConstruct
and WeldClientProxy
,它们是由 Weld 子类(interceptors/decorators)实现的接口and/or 客户端代理 - 请参阅那些 类 的 javadoc 了解更多信息。
所以如果你必须这样做,那么你可以像这样添加对 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
from which you can the retrieve the underlying contextual instance。这是我能让你最接近你所追求的。
一个常见的选择是:
- 获取要解包的实例的 Bean
- 获取其范围 (
bean.getScope()
) - 从 bean 管理器(可注入)获取与范围关联的上下文
- 如果在 CDI 上下文中可用,请执行
context.get(bean)
以获取未包装的实例(在某些情况下您根本无法获取它)。