CDI进阶第一步 CDI拦截器
CDI对象做拦截器,其实就是几个关键的注解。
@Interceptors
@AroundInvoke
这两个注解十分关键。还有两个概念,目标类与拦截器类。
目标类就是我们的CDI对象。拦截器类就是控制目标类运行的拦截器,这个非常好理解。
@AroundInvoke是加上目标类上,或者是目标类的某个方法上。
而@AroundInvoke是加在拦截器的方法上,一个拦截器只能有一个方法加@AroundInvoke注解。在这个方法的方法参数里,放一个InvocationContext对象,可以获取目标类对象和要拦截的方法对象。所有的操作都是通过InvocationContext来进行的。
我讲解完了原理,写个代码试验一下。
下面这是简单的目标类:
package com.rschy.cdiaop;
import javax.enterprise.context.RequestScoped;
import javax.interceptor.Interceptors;
@RequestScoped
public class HelloBean {
@Interceptors(HelloInterceptor.class)
public String greeting(){
return "world!";
}
}
可以看到是在方法上加上了注解,表示拦截这个方法的是HelloInterceptor类。
再看看这个拦截器类的代码:
package com.rschy.cdiaop;
import javax.interceptor.AroundInvoke;
import javax.interceptor.InvocationContext;
public class HelloInterceptor {
@AroundInvoke
public Object invoke(InvocationContext context) throws Exception{
return "Hello,"+context.proceed();
}
}
可以看到这个拦截器的作用就是修改被拦截方法的返回值。
然后我们在servlet中试一试。
package com.rschy.cdiaop;
import java.io.IOException;
import javax.inject.Inject;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@WebServlet("/hello.html")
public class HelloServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
@Inject
private HelloBean service;
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
resp.getWriter().append(service.greeting());
}
}
可以看到返回值被成功地修改了。此外,还可以修改传递过去的对象等等。有兴趣的同学可以自己试一试。