当 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(@ApplicationScoped
、RequestScoped
、...)确实被代理了,你没有得到实际的实例,你得到的是 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
作为标记接口实现。
我 运行 weblogic 中的 2 个示例(我使用了一个具有依赖范围的 bean):
1)bean 没有任何拦截器或装饰器:bean 没有被代理
2)bean 有一个拦截器:bean 被代理了
我认为CDI中有两种类型的代理:
1) 客户端代理:该代理覆盖 bean class 的所有非私有方法,当调用这些被覆盖的方法时,代理查找正确的实例(或第二类代理) bean,然后将调用转发到实际的 bean 实例(基于 this link)。对于从属范围,未创建此代理
2)还有一个应用拦截器和装饰器的代理,它是在bean有装饰器或拦截器时创建的
我对第二类代理的假设是否正确?规范对此有任何说明吗?
您确实进行了很好的调查,并且您在很大程度上是正确的。 详情如下。
代理服务器
普通作用域的 bean(@ApplicationScoped
、RequestScoped
、...)确实被代理了,你没有得到实际的实例,你得到的是 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
作为标记接口实现。