JAVA拦截机制仅适用于CDI

JAVA拦截机制仅适用于CDI,java,jakarta-ee,cdi,interceptor,Java,Jakarta Ee,Cdi,Interceptor,我试图用JAVA创建一个拦截机制的示例。我的问题是 1) 为什么它只适用于注入的对象,而不使用简单的构造函数 2) 在没有CDI和仅使用构造函数的情况下,如何拦截?因为我想使用带有一些参数的构造函数(不是默认构造函数) 工作代码 非工作代码 其他类别(两种情况下相同) SimpleGreeting.java @MyInterceptorBinding public class SimpleGreeting { public SimpleGreeting()

我试图用JAVA创建一个拦截机制的示例。我的问题是

1) 为什么它只适用于注入的对象,而不使用简单的构造函数

2) 在没有CDI和仅使用构造函数的情况下,如何拦截?因为我想使用带有一些参数的构造函数(不是默认构造函数)

工作代码 非工作代码 其他类别(两种情况下相同) SimpleGreeting.java

    @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)。如果您自己进行实例化,那么容器就无法完成此类工作

  • 有。例如,对于AspectJ,您可以使用运行时编织将这些拦截代码添加到有效的类中


  • 诚然,两者在实现方式上可能有所不同,但不应改变我使用逻辑的方式。否则,方便的意义是什么?我对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();
    }