我试图在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();
}
}
答案 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)
我认为这是因为拦截机制是基于代理的。这意味着,虽然您认为您指的是Foo
,但它实际上是Foo
的代理,拦截逻辑用于代理,并将调用委托给真实的Foo
实例。
因此容器需要管理bean的注入(因此它可以创建代理并注入代理而不是实际的bean)。如果您自己实例化,则容器无法进行此类工作。
是的。例如,对于AspectJ,您可以使用运行时编织将这些拦截代码添加到有效的类中。