一、拦截器方法
EJB3可以通过拦截器对Bean方法进行拦截和覆盖。这有些象AOP中的around。通过AOP的around方法,可以修改被拦截方法的返回值、参数值,甚至可以取消被拦截方法的执行。EJB3的拦截器可以用在无状态Session Bean、有状态Session Bean和消息驱动Bean(MDB)的方法中。实现拦截器的最简单的方法是使用拦截器方法。也就是说,只要在当前的Bean中使用@AroundInvoke对某个方法进行注释(关于拦截器的类都在javax.interceptor包中),那么这个方法就会变成拦截器方法,该拦截器方法会拦截当前Bean中的所有方法。实现过程如下:
上面的Stateful Session Bean中定义了两个拦截器方法和一个Bean方法。当客户端调用greet方法时,EJB容器会先调用myInterceptorMethod1方法,然后会调用myInterceptorMethod2方法,最后会调用greet方法。使用拦截器方法时要注意如下几点:
1. 拦截器方法必须有一个返回值,返回值类型是Object。
2. 拦截器方法只能有一个参数,而且该参数类型必须是javax.interceptor.InvocationContext。
3. 只有调用InvocationContext接口的proceed方法,EJB容器才会调用下一个拦截器方法或被拦截的Bean方法。
4. 由于proceed方法要求抛出一个Exception异常,因此,拦截器方法必须抛出一个Exception异常,或在拦截器方法中使用try...catch来捕捉proceed方法抛出的异常。
二、拦截器类
有一些拦截器方法会拦截器不同Bean中的方法,在这种情况下,需要将拦截器方法放在一个单独的类中。这个类就叫拦截器类。下面是一个拦截器类的代码:
为了使用该拦截器类,需要在SessionBean或MDB中使用@Interceptors来指定要使用的拦截器类。代码如下:
如果有多个拦截器类,可以使用如下的代码来指定这些拦截器类:
如果指定了多个拦截器类和拦截器方法,就涉及到一个调用顺序的问题。EJB容器会先调用拦截器类中的拦截器方法、如果有多个拦截器类被指定,按指定的顺序进行调用。也就是说,MyInterceptor类中的拦截器方法会最先被调用,然后是MyInterceptor1类中的拦截器方法。最后会调用在Bean中定义的拦截器方法(myInterceptorMethod1和myInterceptorMethod2)。
在默认情况下,拦截器类将拦截所有的Bean方法,但可以使用@ExcludeClassInterceptors注释来阻止拦截器对某个Bean方法进行拦截。如在GreeterBean类中还有一个getValue方法,那么阻止该方法被拦截的代码如下:
EJB3可以通过拦截器对Bean方法进行拦截和覆盖。这有些象AOP中的around。通过AOP的around方法,可以修改被拦截方法的返回值、参数值,甚至可以取消被拦截方法的执行。EJB3的拦截器可以用在无状态Session Bean、有状态Session Bean和消息驱动Bean(MDB)的方法中。实现拦截器的最简单的方法是使用拦截器方法。也就是说,只要在当前的Bean中使用@AroundInvoke对某个方法进行注释(关于拦截器的类都在javax.interceptor包中),那么这个方法就会变成拦截器方法,该拦截器方法会拦截当前Bean中的所有方法。实现过程如下:
@Stateful
public class GreeterBean implements Greeter
{
@AroundInvoke
public Object myInterceptorMethod1(InvocationContext ic) throws Exception
{
System.out.println( " myInterceptorMethod1: " + ic.getMethod().getName());
obj = ic.proceed();
}
@AroundInvoke
public Object myInterceptorMethod2(InvocationContext ic) throws Exception
{
System.out.println( " myInterceptorMethod2: " + ic.getMethod().getName());
obj = ic.proceed();
}
@Override
public String greet(String name)
{
return " hello " + name;
}
}
public class GreeterBean implements Greeter
{
@AroundInvoke
public Object myInterceptorMethod1(InvocationContext ic) throws Exception
{
System.out.println( " myInterceptorMethod1: " + ic.getMethod().getName());
obj = ic.proceed();
}
@AroundInvoke
public Object myInterceptorMethod2(InvocationContext ic) throws Exception
{
System.out.println( " myInterceptorMethod2: " + ic.getMethod().getName());
obj = ic.proceed();
}
@Override
public String greet(String name)
{
return " hello " + name;
}
}
上面的Stateful Session Bean中定义了两个拦截器方法和一个Bean方法。当客户端调用greet方法时,EJB容器会先调用myInterceptorMethod1方法,然后会调用myInterceptorMethod2方法,最后会调用greet方法。使用拦截器方法时要注意如下几点:
1. 拦截器方法必须有一个返回值,返回值类型是Object。
2. 拦截器方法只能有一个参数,而且该参数类型必须是javax.interceptor.InvocationContext。
3. 只有调用InvocationContext接口的proceed方法,EJB容器才会调用下一个拦截器方法或被拦截的Bean方法。
4. 由于proceed方法要求抛出一个Exception异常,因此,拦截器方法必须抛出一个Exception异常,或在拦截器方法中使用try...catch来捕捉proceed方法抛出的异常。
二、拦截器类
有一些拦截器方法会拦截器不同Bean中的方法,在这种情况下,需要将拦截器方法放在一个单独的类中。这个类就叫拦截器类。下面是一个拦截器类的代码:
package
service;
import javax.interceptor.AroundInvoke;
import javax.interceptor.InvocationContext;
public class MyInterceptor
{
@AroundInvoke
public Object interceptorMethod(InvocationContext ic) throws Exception
{
System.out.println( " MyInterceptor: " + ic.getMethod().getName());
return ic.proceed();
}
}
import javax.interceptor.AroundInvoke;
import javax.interceptor.InvocationContext;
public class MyInterceptor
{
@AroundInvoke
public Object interceptorMethod(InvocationContext ic) throws Exception
{
System.out.println( " MyInterceptor: " + ic.getMethod().getName());
return ic.proceed();
}
}
为了使用该拦截器类,需要在SessionBean或MDB中使用@Interceptors来指定要使用的拦截器类。代码如下:
@Stateful
@Interceptors(MyInterceptor. class )
public class GreeterBean implements Greeter
{
@AroundInvoke
public Object myInterceptorMethod1(InvocationContext ic) throws Exception
{
System.out.println( " myInterceptorMethod1: " + ic.getMethod().getName());
obj = ic.proceed();
}
@AroundInvoke
public Object myInterceptorMethod2(InvocationContext ic) throws Exception
{
System.out.println( " myInterceptorMethod2: " + ic.getMethod().getName());
obj = ic.proceed();
}
@Override
public String greet(String name)
{
return " hello " + name;
}
}
@Interceptors(MyInterceptor. class )
public class GreeterBean implements Greeter
{
@AroundInvoke
public Object myInterceptorMethod1(InvocationContext ic) throws Exception
{
System.out.println( " myInterceptorMethod1: " + ic.getMethod().getName());
obj = ic.proceed();
}
@AroundInvoke
public Object myInterceptorMethod2(InvocationContext ic) throws Exception
{
System.out.println( " myInterceptorMethod2: " + ic.getMethod().getName());
obj = ic.proceed();
}
@Override
public String greet(String name)
{
return " hello " + name;
}
}
如果有多个拦截器类,可以使用如下的代码来指定这些拦截器类:
@Interceptors({MyInterceptor.
class
, MyInterceptor1.
class
})
如果指定了多个拦截器类和拦截器方法,就涉及到一个调用顺序的问题。EJB容器会先调用拦截器类中的拦截器方法、如果有多个拦截器类被指定,按指定的顺序进行调用。也就是说,MyInterceptor类中的拦截器方法会最先被调用,然后是MyInterceptor1类中的拦截器方法。最后会调用在Bean中定义的拦截器方法(myInterceptorMethod1和myInterceptorMethod2)。
在默认情况下,拦截器类将拦截所有的Bean方法,但可以使用@ExcludeClassInterceptors注释来阻止拦截器对某个Bean方法进行拦截。如在GreeterBean类中还有一个getValue方法,那么阻止该方法被拦截的代码如下:
@ExcludeClassInterceptors
public String getValue()
{
return " abcd " ;
}
public String getValue()
{
return " abcd " ;
}
使用@ExcludeClassInterceptors只能阻止拦截器类中的拦截器方法对Bean方法的拦截,而在Bean中定义的拦截器方法仍然会拦截Bean方法。
本文转自 androidguy 51CTO博客,原文链接:http://blog.51cto.com/androidguy/214417,如需转载请自行联系原作者