JAVA拦截机制仅适用于CDI

时间:2017-06-01 03:14:23

标签: java java-ee cdi interceptor

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

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

2)如果没有CDI并仅使用构造函数,我如何拦截?因为我想使用带有一些参数的构造函数(非默认构造函数)。

工作代码

    public class StartingPoint extends HttpServlet 
    {

      private static final long serialVersionUID = 1L;
      // With CDI
      @Inject
      SimpleGreeting greeting;

      public void doGet(HttpServletRequest request,HttpServletResponse response) throws ServletException, IOException
      {
          System.out.println("Started");
          System.out.println(greeting.abc());
      }

    }

不工作代码

    public class StartingPoint extends HttpServlet 
    {

      private static final long serialVersionUID = 1L;

      public void doGet(HttpServletRequest request,HttpServletResponse response) throws ServletException, IOException
      {
          // With simple constructor
          SimpleGreeting greeting = new SimpleGreeting();
          System.out.println("Started");
          System.out.println(greeting.abc());
      }

    }

其他类(两种情况都相同)

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();
        }
    }

3 个答案:

答案 0 :(得分:1)

如果您查看javadoc:http://docs.oracle.com/javaee/6/api/javax/interceptor/InterceptorBinding.html,您会注意到@InterceptorBinding是与 beans 关联的注释(即由容器作为EJB管理的实例,托管豆等):

拦截器绑定是中间注释,可用于将拦截器与目标 bean 相关联

答案 1 :(得分:0)

  

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。

答案 2 :(得分:0)

  1. 我认为这是因为拦截机制是基于代理的。这意味着,虽然您认为您指的是Foo,但它实际上是Foo的代理,拦截逻辑用于代理,并将调用委托给真实的Foo实例。

    因此容器需要管理bean的注入(因此它可以创建代理并注入代理而不是实际的bean)。如果您自己实例化,则容器无法进行此类工作。

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