首页 > 代码库 > 会话EJB系列(五)拦截器

会话EJB系列(五)拦截器

上一篇文章《会话EJB系列(四)SessionBean事务管理》中,我们介绍了SessionBean的事务管理机制。

本文主题‘拦截器’,详细介绍其用途、作用、与Spring框架AOP的对比,并介绍其初步用法。

  

 一.简介

        企业级应用中经常面对的事务管理、安全检查、缓存、对象池管理等,为此Spring框架提供了AOP方式,灵活控制业务方法!而EJB3没有提供AOP支持,那么他又是如何应对的呢?

 

       JavaEE规范中提供的横切性服务:事务管理和安全检查。

       EJB容器实现JavaEE规范

               用CMT解决事务管理问题

               用JAAS以声明的方式解决安全检查,权限控制。

 

       而对于其它具有横切性质的服务,JavaEE规范依然显得力不从心。 

       为了弥补缺乏AOP支持的不足,EJB3提供了拦截器支持。

               本质是轻量级AOP实现,作用于AOP如出一辙

               将多个业务方法中通用逻辑从业务方法中抽离出来,放在拦截中实现,实现代码复用。

 

二.EJB3的拦截器和Spring的AOP对比

(一)不同点

       Spring的AOP实现提供了@Before,@AfterReturning,@AfterThrowing,@After,@Around等大量的Annotation,用于定义功能丰富增强处理。

       而EJB提供的拦截器机制只能算是一种轻量级的AOP实现,功能比较有限。 

(二)相同点

       均使用@AroundInvoke修饰拦截方法,方法中定义的就是分布于多个模块中,具有横切性质的通用处理代码。

 

三.使用方法

(一)定义一个拦截器

       首先定义一个拦截器类,并用@AroundInvoke修饰其中的方法,这个方法将会在SessionBean的多个方法被调用时“切入”。 

 

import javax.interceptor.AroundInvoke;import javax.interceptor.InvocationContext;public class MyInterceptor {	@AroundInvoke	public Object log(InvocationContext ctx) throws Exception {		long start=System.currentTimeMillis();		System.out.println("----拦截器运行开始----");		try {			Object rvt = ctx.proceed();			return rvt;		} catch (Exception e) {			System.out.println("----拦截器运行出错----");			throw e;		} finally {			long time = System.currentTimeMillis() - start;			System.out.println("----拦截器运行结束----");			System.out.println("拦截器运行用时:" + time + "ms");		}	}}

 

        可以看出,这个拦截器不需要实现任何接口,或继承什么基类,只要用@AroundInvoke Annotation标记该拦截器类的方法就可以。

       要指出的是,@AroundInvoke修饰的方法必须满足如下格式:

                public Object  ****(InvocatonContext   cxt)   throws Exception

        形参InvocatonContext  对象中,包含了被调用方法的详细信息,如:

                1.Map<String,Object> getContextData():返回一个Map对象,该Map对象里封装了本次调用或生命周期回调相关上下文信息。

                2.Method getMethod():获取被拦截的方法

                3.Object[] getParameter();获取被拦截的业务方法的实际参数。

                4.Object getRarget();获取被拦截的Session Bean实例

                5.Object proceed():调用InvocationContext的该方法时,就是回调拦截方法,执行被拦截方法。

                6.void setParameters(Object[] params):修改被拦截的业务方法的实际参数

(二)定义被拦截对象

1.定义SessionBean业务接口并声明3个方法

import javax.ejb.Remote;@Remotepublic interface HelloWorldBean {		String hello1(String name);	void hello2();	void exclude();}


         接口中无需使用任何Annotation

       只要在Bean实现类中使用@Interceptors来修饰即可

2.定义Bean实现类,并用@Interceptors修饰

        @Interceptors是EJB3为依赖注入提供的Annotation ,用于修饰Bean类或业务方法,使用时需要用value属性指明拦截器类的类名。

              若修饰某个Bean实现类,则对类中的所有方法均起作用

              若修饰某个Bean实现类中的方法,则只对标记的方法起作用。

               若用@ExcludeClassInterceptors修饰Bean内的某个业务上,则表示拦截器对该标记方法不起作用

import javax.ejb.Stateless;import javax.interceptor.AroundInvoke;import javax.interceptor.Interceptors;import javax.interceptor.InvocationContext;@Stateless(mappedName = "HelloWorldBeanImpl")@Interceptors(MyInterceptor.class)public class HelloWorldBeanImpl implements HelloWorldBean {	public String hello1(String name) {		System.out.println("我是被拦截器拦击的方法:hello1");	}	public void hello2() {		System.out.println("我是被拦截器拦截的方法:hello2");	}	public void exclude() {		System.out.println("我是被拦截器排除在外的方法:exclude");	}}


相关EJB拦截器的使用文章,请参考《EJB3.0中拦截器的实现

 

总结

       从上述文章可以看出,EJB3的拦截器是一种轻量级AOP机制,和Spring框架中的AOP如出一辙。

       而且使用极为简单,开发者只需要如下步骤即可:

               (1)定义一个普通类。如何把它标记为拦截器类呢?只需要使用@AroundInvoke修饰一个具有public Object  ****(InvocatonContext   cxt)   throws Exception签名的方法即可。

               (2)在所有被拦截的EJB3的Bean实现类、业务方法上使用@Interceptors修饰

               (3)如果想在EJB中某个方法中不使用拦截器,则使用@ExcludeClassInterceptors修饰该方法即可。

 

 

 

会话EJB系列(五)拦截器