当 bean 具有拦截器或装饰器时,CDI 中的 bean 代理规则是什么?

what are proxing rules in CDI for beans when they have interceptor or decorator?

我 运行 weblogic 中的 2 个示例(我使用了一个具有依赖范围的 bean):

1)bean 没有任何拦截器或装饰器:bean 没有被代理

2)bean 有一个拦截器:bean 被代理了

我认为CDI中有两种类型的代理:

1) 客户端代理:该代理覆盖 bean class 的所有非私有方法,当调用这些被覆盖的方法时,代理查找正确的实例(或第二类代理) bean,然后将调用转发到实际的 bean 实例(基于 this link)。对于从属范围,未创建此代理

2)还有一个应用拦截器和装饰器的代理,它是在bean有装饰器或拦截器时创建的

我对第二类代理的假设是否正确?规范对此有任何说明吗?

您确实进行了很好的调查,并且您在很大程度上是正确的。 详情如下。

代理服务器

普通作用域的 bean(@ApplicationScopedRequestScoped、...)确实被代理了,你没有得到实际的实例,你得到的是 client proxy. 使用 而非 正常范围的 @Dependent,您基本上每次都想注入新实例,因此无需代理它。

上面在 CDI 规范中提到了一些内容,尽管给出的实现并不精确 space 他们可以在其中进行操作 - 用户不应该真正关心他们是否有代理,因为调用他们的方法只是工作很好。

拦截器和装饰器

继续讨论拦截器——据我所知,规范对此只字未提,并让实现自由选择如何处理它。以下详细信息是 Weld-specific 尽管据我所知,OWB 也有相似之处。无论如何,实现它的选项并不多。

对于每个 interceptor/decorator,都会创建一个 "proxy",实际上是一个子类,它允许 interception/decoration 发生。这个子类替换了原始 bean,所有调用都通过它(例如,它在底层 bean 存储中而不是原始实例中)。

同样,从用户的角度来看,这没有什么区别,您不必担心。

proxies/sublasses

的额外工具

有时,很少,而且很可能只有在开发 CDI 库时,您可能真正需要查看注入的 bean 是客户端代理还是子类。 Weld 为此提供了工具,每个具有客户端代理的 bean 都在实现来自 Weld API 的 WeldClientProxy 接口。此接口允许您获取实际实例和一些元数据。 同样,每个拦截和修饰的 bean 都将 WeldContruct 作为标记接口实现。