JAVA拦截机制仅适用于CDI
我试图用JAVA创建一个拦截机制的示例。我的问题是 1) 为什么它只适用于注入的对象,而不使用简单的构造函数 2) 在没有CDI和仅使用构造函数的情况下,如何拦截?因为我想使用带有一些参数的构造函数(不是默认构造函数) 工作代码 非工作代码 其他类别(两种情况下相同) SimpleGreeting.javaJAVA拦截机制仅适用于CDI,java,jakarta-ee,cdi,interceptor,Java,Jakarta Ee,Cdi,Interceptor,我试图用JAVA创建一个拦截机制的示例。我的问题是 1) 为什么它只适用于注入的对象,而不使用简单的构造函数 2) 在没有CDI和仅使用构造函数的情况下,如何拦截?因为我想使用带有一些参数的构造函数(不是默认构造函数) 工作代码 非工作代码 其他类别(两种情况下相同) SimpleGreeting.java @MyInterceptorBinding public class SimpleGreeting { public SimpleGreeting()
@MyInterceptorBinding
public class SimpleGreeting
{
public SimpleGreeting()
{
}
public String abc()
{
return "Greet";
}
}
MyInterceptorBinding.java
@Inherited
@InterceptorBinding
@Retention(RUNTIME)
@Target({ METHOD, TYPE })
public @interface MyInterceptorBinding {
}
MyInterceptor.java
@Interceptor
@MyInterceptorBinding
public class MyInterceptor
{
public MyInterceptor()
{
}
@AroundInvoke
public Object log(InvocationContext context) throws Exception
{
System.out.println("Intercepted");
return context.proceed();
}
}
1) 为什么它只适用于注入的对象,而不使用简单的构造函数
当使用CDI注入问候语时,封面下会出现一些“魔力”。如果CDI只能调用一个简单的构造函数,那么它就不是一种非常有用的技术
因此,如果您有以下代码:
@Inject
SimpleGreeting greeting;
实际上,在幕后发生的事情是这样的:
SimpleGreeting greeting = injectGreeting();
private SimpleGreeting injectGreeting() {
if ( /* MyInterceptorBinding annotation present on SimpleGreeting class */)
new MyInterceptor().log(context); // this prints "Intercepted"
return new SimpleGreeting();
}
2) 有没有办法在不使用CDI和只使用构造函数的情况下进行拦截
从技术上讲是的,但拦截是最简单的方法。我脑海中唯一能想到的另一种方法是像ASM这样的字节码操作框架。如果你看一下javadoc:,你会注意到,
@InterceptorBinding
是一个与bean相关联的注释(即容器作为EJB、托管bean等管理的实例):
拦截器绑定是可用于将拦截器与目标bean关联的中间注释
Foo
,但它实际上是Foo
的代理,对其执行拦截逻辑,并将调用委托给真实的Foo
实例
因此,容器将需要管理bean的注入(因此它可以创建代理并注入代理而不是实际的bean)。如果您自己进行实例化,那么容器就无法完成此类工作诚然,两者在实现方式上可能有所不同,但不应改变我使用逻辑的方式。否则,方便的意义是什么?我对CDI和注释还不熟悉。请你详细说明一下,我怎样才能让它在我的例子中起作用?我不明白你真正想要实现什么。您希望在哪个类上有一个带参数的构造函数?假设在SimpleRegreeting类上,我希望有一个带参数的构造函数,并希望使用该构造函数实例化问候对象。正如@Andy Guibert所说,没有CDI,您无法轻松使用拦截器,如果您“手动”实例化问候对象,则会破坏CDI。但是,您可以使用构造函数注入或setter注入将cdibean注入到另一个cdibean中。您希望在构造函数中包含哪些对象?也许有一种方法可以重构你的代码,让它与你的工作。我们需要更多关于您真正想要做什么的信息。这是因为具有拦截CDI的能力是可能的。这是运行时功能。这就是为什么它不能用于普通实例化CDI甚至支持带有参数的构造函数,只要这些参数是可注入的。此外,您还可以使用
@AroundConstruct
拦截器使其拦截对象创建(因此基本上是构造函数invocaiton)。在使用CDI的同时,这一切对你有帮助吗?
@Inject
SimpleGreeting greeting;
SimpleGreeting greeting = injectGreeting();
private SimpleGreeting injectGreeting() {
if ( /* MyInterceptorBinding annotation present on SimpleGreeting class */)
new MyInterceptor().log(context); // this prints "Intercepted"
return new SimpleGreeting();
}