从 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。这是我能让你最接近你所追求的。

一个常见的选择是:

  1. 获取要解包的实例的 Bean
  2. 获取其范围 (bean.getScope())
  3. 从 bean 管理器(可注入)获取与范围关联的上下文
  4. 如果在 CDI 上下文中可用,请执行 context.get(bean) 以获取未包装的实例(在某些情况下您根本无法获取它)。