EJB提供了拦截器功能,它可以将部分统一的业务逻辑抽象为AOP切面,可以用于日志记录、统一安全检查、参数校验等场景。这篇笔记我们介绍EJB中拦截器的使用。
在EJB实现类中,我们可以定义一个@AroundInvoke
方法,它实现了一种环绕切面。
package com.gacfox.netstore.ejb;
import com.gacfox.netstore.api.HelloService;
import org.jboss.logging.Logger;
import javax.ejb.Stateless;
import javax.interceptor.AroundInvoke;
import javax.interceptor.InvocationContext;
@Stateless
public class HelloServiceImpl implements HelloService {
private static final Logger logger = Logger.getLogger(HelloServiceImpl.class);
@Override
public String hello() {
return "Hello, EJB!";
}
@AroundInvoke
private Object logAroundInvoke(InvocationContext context) throws Exception {
logger.info("invoking start");
Object result = context.proceed();
logger.info("invoking end");
return result;
}
}
代码中,logAroundInvoke()
是一个环绕切面方法,它的方法签名是固定的,方法体中,我们在被拦截的代码逻辑执行前和执行后打印了日志信息。当hello()
方法被调用时,这个环绕切面就会起作用,在hello()
的执行前后插入环绕切面逻辑。InvocationContext
对象包含了方法调用相关的信息,我们可以从其中获取传入的方法名、参数等。
前面我们在一个EJB实现类内部使用了@AroundInvoke
环绕拦截方法,它只能作用于一个EJB内,我们还可以定义单独的拦截器并配置到多个EJB上,这样的拦截器更具通用性,下面是一个例子。
package com.gacfox.netstore.ejb;
import org.jboss.logging.Logger;
import javax.interceptor.AroundInvoke;
import javax.interceptor.InvocationContext;
public class LogInterceptor {
private static final Logger logger = Logger.getLogger(LogInterceptor.class);
@AroundInvoke
public Object logAroundInvoke(InvocationContext context) throws Exception {
logger.info("invoking start");
Object result = context.proceed();
logger.info("invoking end");
return result;
}
}
package com.gacfox.netstore.ejb;
import com.gacfox.netstore.api.HelloService;
import org.jboss.logging.Logger;
import javax.ejb.Stateless;
import javax.interceptor.Interceptors;
@Stateless
@Interceptors(LogInterceptor.class)
public class HelloServiceImpl implements HelloService {
private static final Logger logger = Logger.getLogger(HelloServiceImpl.class);
@Override
public String hello() {
return "Hello, EJB!";
}
}
在EJB实现了类上我们使用了@Interceptors
注解,这个注解表示将拦截器类应用到该EJB上,它可以标注在类上也可以标注在方法上,前者拦截器对类的所有方法起效,后者拦截器只对标注的方法起效。此外,我们也可以标注多个拦截器,通过InvocationContext
多个拦截器之间可以传递数据,形成链式处理逻辑。