当具有拦截器或装饰器的bean在CDI中有什么处理规则?

时间:2018-10-16 07:56:03

标签: java proxy cdi

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

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

2)该bean具有拦截器:该bean已被代理

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

1)客户端代理:此代理会覆盖Bean类的所有非私有方法,当调用这些覆盖的方法时,代理会查找Bean的正确实例(或第二种代理),然后转发调用到实际的bean实例上(基于this链接)。对于依赖范围,不会创建此代理

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

我对第二种代理的假设正确吗?规范对此有何规定?

1 个答案:

答案 0 :(得分:2)

您确实做了一个很好的调查,并且在大多数情况下您是对的。 这是详细信息。

代理

确实可以代理普通作用域的bean(@ApplicationScopedRequestScoped,...),您无法掌握实际实例,而得到的只是一个client proxy。 使用不是普通作用域的@Dependent,您基本上希望每次都注入新实例,因此无需代理它。

以上内容在CDI规范中有所提及,尽管不够精确,不能为他们提供可操作的实现空间-用户不必真正关心是否有代理,也可以调用方法正常工作。

拦截器和装饰器

继续使用拦截器-我所了解的规范对此一无所知,并让实现者自由选择要怎么做。以下细节是 Weld-specific (特定于焊接的),尽管据我回忆,OWB也有类似之处。无论如何,实际上没有太多选择。

对于每个拦截器/装饰器,都会创建一个“代理”,实际上是一个子类,该子类允许进行拦截/装饰。该子类将替换原始Bean,并且所有调用都将通过该子类(例如,它在基础Bean存储区中而不是原始实例中)。

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

用于代理/子服务器的额外工具

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