1.定义在外部类的拦截器执行的优先级比定义在Bean类中的拦截器要高。
2.拦截器方法能够访问到触发它的业务方法的相关信息, 比如方法名、调用参数。
通过对业务方法调用的追踪记录,系统管理员可以分析系统的安全漏洞,或者回放某位用户执行的操作。
3.EJB容器会根据定义拦截器的顺序来依次触发对它们的调用。
即各自在@Interceptors注释中的先后顺序,其次执行定义在Bean类内部的拦截器。
4.EJB3.0引入的拦截器为EJB组件注入了AOP活力。
使得业务代码同拦截器代码完全分离。
5.使用拦截器的场合,非常多,比如日志、执行审计、安全性检查等。示例代码:
package examples.stateless.interceptors;
import javax.interceptor.AroundInvoke;
import javax.interceptor.InvocationContext;
public class AuditorInterceptor {
@AroundInvoke
public Object checkCost(InvocationContext inv) throws Exception {
if (inv.getMethod().getName().startsWith("getTax")) {
Object[] o = inv.getParameters();
double cost = ((Double)o[0]).doubleValue();
if (cost > 50) {
System.out.println("Cost is > 50!");
}
}
return inv.proceed();
}
}
禁用拦截器
@ExcludeClassInterceptors注解可以禁止所有定义于类上的拦截器,
@ExcludeDefaultInterceptors注解则可以禁用所有定义于XML中的默认拦截器。
拦截器可以提供一种封装性能监测逻辑的机制,使用XML绑定是应用拦截器的一种更好的方式。
拦截器与其所拦截的EJB同处于一个ENC中。
位于拦截器类中的@AroundInvoke方法,与其所拦截的业务方法执行于同一个Java调用堆栈、同一个事务和安全上下文中。
在拦截回调方法时,你不能抛出任何可控式异常,因此,所有可控式异常都是必须被捕获并包装成EJBException。
异常处理
拦截器的生命周期
拦截器与其拦截的EJB具有相同的生命周期。
但是,拦截器和与之相关的bean有着同样的限制。例如,如果所拦截的并非stateful session bean ,那么你就不能将extended persistent context注入到拦截器中。
异常处理
拦截器中的异常处理非常简单,却又功能强大。
终止方法的调用 Aborting a Method Invocation
参数校验是一种在业务方法的处理逻辑执行之前检查传入参数是否合法的业务逻辑。
import javax.annotation.Resource;
import javax.interceptor.AroundInvoke;
import javax.interceptor.InvocationContext;
public class CheckValidation {
@Resource int minimumCheckNumber;
@AroundInvoke
public Object validateCheck(InvocationContext ctx)throws Exception{
CheckDO check = ctx.getParameters()[1];
if(check.checkNumber < minimumCheckNumber){
throw new PaymentException("Check number is too low!");
}
return ctx.proceed();
}
}
支票编号的最小值是通过<env-entry>被注入到拦截器的minimumCheckNumber变量中的
校验只是你想在@AroundInvoke方法中终止EJB调用的一个例子,另一个例子则是实现自己的安全框架。也可以吧
EJB和规则引擎集成在一起,利用规则引擎,对用户以及调用方法和传入参数进行分析,从而判断出用户是否被
允许调用该方法。
catch and rethrow Exceptions
示例代码:
@ApplicationException(rollback=true)
public class DatabaseDeadlockException extends java.sql.SQLException{
public DatabaseDeadlockException(Exception cause){
super(cause);
}
}
@ApplicationException(rollback=true)
public class DatabaseCursorNotAvailable extends java.sql.SQLException{
public DatabaseCursorNotAvailable (Exception cause){
super(cause);
}
}
public class MySQLExceptionHandler {
public Object handleException(InvocationContext ctx) Exception {
try{
return ctx.proceed();
} catch(SQLException sql){
int ernum = sql.getErrorCode();
switch(ernum){
case 32343:
throw new DatabaseDeadlockException (sql);
case 22211:
throw new DatabaseCursorNotAvailable (sql);
...
Default:
throw new RollbackAlwaysOnException(sql);
}
}
}
}