可以说拦截器是AOP在EJB world里面的实现,拦截器可以用于SesstionBean和Message Driven Bean。拦截器可以用Descriptor file或者annotation来实现,但是基本上我们都是用annotation来实现。拦截器可以用来
看下@Interceptors的J2EE文档,发现它的内容如下:
@Target(value={TYPE,METHOD})
@Retention(value=RUNTIME)
public @interface Interceptors{
public Class[] value();
}
@Interceptors可以用在类级别,也可以用在方法上,用在类级别上,就代表整个类的所有方法在被调用的时候都会让拦截器的方法被调用,而用在method上,则只有该方法的调用之前会让拦截器的方法被调用。
举个例子,HelloWorldBean实现IHelloWorld的业务接口,有两个方法SayHello1()和SayHello2(),拦截器打印出哪个方法被调用。
@Interceptors(HelloInterceptor.class)
@Stateless
public class HelloWorldBean implements IHelloWorld{
public void SayHello1(){
.......
}
public void SayHello2(){
......
}
}
public class HelloInterceptor{
//含有AroundInvoke注解的方法就是拦截器方法
@AroundInvoke
public Object getMethod(InvocationContext invocationContext) throws Exception{
System.out.println("method "+ invocationContext.getMethod().getName() +" invoked");
return invocationContext.proceed();
}
}
上面这个例子是将@Interceptors用于类级别的,用于方法级别的时候就对那个特定的方法的调用进行拦截。
其实还可以定义default Interceptor,它可以用来拦截所有bean的所有方法。如下:
<assembly-descriptor>
<interceptor-binding>
<ejb-name>*</ejb-name>
<interceptor-class>
ejb.impl.DefaultInterceptor
</interceptor-class>
</interceptor-binding>
</assembly-descriptor>
现在问题来了,一个方法被调用的时候,可能会有多个拦截器发生作用(默认拦截器、类级别的和方法级别的),他们的调用顺序是什么的,答案是从大的范围到小的范围。即default interceptor->class interceptor->method interceptor。
对于InvocationContext这个接口,
public interface InvocationContext {
public Object getTarget();
public Method getMethod();
public Object[] getParameters();
public void setParameters(Object[]);
public java.util.Map<String,Object> getContextData();
public Object proceed() throws Exception;
}
有几个方法需要说明下:
InvocationContext.proceed() method: This tells the
container that it should proceed to the next Interceptor in the execution chain or call the
intercepted business method. On the other hand, not calling the proceed method will bring
processing to a halt and avoid the business method (and any other Interceptor down the
execution chain) from being called.
InvocationContext.getContextData() method:返回的的这个Map可以在整个的interceptor chain中共享,这意味着可以在同一个bean的多个interceptor中共享信息。
看下@Interceptors的J2EE文档,发现它的内容如下:
@Target(value={TYPE,METHOD})
@Retention(value=RUNTIME)
public @interface Interceptors{
public Class[] value();
}
@Interceptors可以用在类级别,也可以用在方法上,用在类级别上,就代表整个类的所有方法在被调用的时候都会让拦截器的方法被调用,而用在method上,则只有该方法的调用之前会让拦截器的方法被调用。
举个例子,HelloWorldBean实现IHelloWorld的业务接口,有两个方法SayHello1()和SayHello2(),拦截器打印出哪个方法被调用。
@Interceptors(HelloInterceptor.class)
@Stateless
public class HelloWorldBean implements IHelloWorld{
public void SayHello1(){
.......
}
public void SayHello2(){
......
}
}
public class HelloInterceptor{
//含有AroundInvoke注解的方法就是拦截器方法
@AroundInvoke
public Object getMethod(InvocationContext invocationContext) throws Exception{
System.out.println("method "+ invocationContext.getMethod().getName() +" invoked");
return invocationContext.proceed();
}
}
上面这个例子是将@Interceptors用于类级别的,用于方法级别的时候就对那个特定的方法的调用进行拦截。
其实还可以定义default Interceptor,它可以用来拦截所有bean的所有方法。如下:
<assembly-descriptor>
<interceptor-binding>
<ejb-name>*</ejb-name>
<interceptor-class>
ejb.impl.DefaultInterceptor
</interceptor-class>
</interceptor-binding>
</assembly-descriptor>
现在问题来了,一个方法被调用的时候,可能会有多个拦截器发生作用(默认拦截器、类级别的和方法级别的),他们的调用顺序是什么的,答案是从大的范围到小的范围。即default interceptor->class interceptor->method interceptor。
对于InvocationContext这个接口,
public interface InvocationContext {
public Object getTarget();
public Method getMethod();
public Object[] getParameters();
public void setParameters(Object[]);
public java.util.Map<String,Object> getContextData();
public Object proceed() throws Exception;
}
有几个方法需要说明下:
InvocationContext.proceed() method: This tells the
container that it should proceed to the next Interceptor in the execution chain or call the
intercepted business method. On the other hand, not calling the proceed method will bring
processing to a halt and avoid the business method (and any other Interceptor down the
execution chain) from being called.
InvocationContext.getContextData() method:返回的的这个Map可以在整个的interceptor chain中共享,这意味着可以在同一个bean的多个interceptor中共享信息。