AOP最近被炒得非常的热,各种各样的AOP框架层出不穷。在AOP方面,我无意于去做一个完整的框架,支持各种AOP的特性,其实从实际我们项目经历上来分析。可以得出,在绝大多数情况下,AOP的很多高级特性是用不上的,比如静态代码注入。为类添加运行时的构造函数,改变类的继承关系等等。其实我们最常用的还是拦截器,关于这个话题,可能是比较有争议的,毕竟每个人的立场和观点是不同的。针对我目前所涉及的应用域来讲,一个完整的拦截器框架已经足够了。
一个典型的拦截器框架至少应该包括三个部分:
1、可声明的拦截点;
2、灵活的拦截器序列;
3、对拦截对象的代理封装;
拦截点可以基于具体的应用环境去灵活申明,这点可以参考Cocoon里的Pipeline。这里不用多说,大家看了后续的拦截点的定义代码就一目了然了。关于拦截器的具体定义,也在随后的部分提供,这里首先探讨被拦截对象的代理的实现机制。
所谓代理,就是对被拦截对象的一个包装,通过该包装类,可以非常自然的对被包装对象添加我们自定义的行为,比如调用拦截器进行拦截操作。
我们来看AOP的代理接口的定义:
package
org.sunny.core.aop;
import
java.lang.reflect.InvocationHandler;
import
org.sunny.exception.SunnyException;
import
java.util.List;
/**
*
该类是一个拦截器的处理中心,所有的业务逻辑的方法调用都会被该类拦截。通过这种机制,
*
在这里就可以统一的实现如下的过滤器:
*
1、方法级鉴权;
*
2、业务日志;
*
3、静态属性过滤。
*
等等功能。此外,你可以实现自己的拦截器,通过如下的接口:
*
< code>
*
< br>org.sunny.core.aop.interceptor.Interceptor
*
< /code>
*
并在全局配置文件里完成拦截器的配置。该拦截器就可以生效。
*
< p>Copyright:
Copyright
(c)
2005< /p>
*
< p>Company:
Sunny虚拟开发组< /p>
*
@author
高雁冰
*
@version
1.0
*/
public
interface
AopProxy
{
/** *设置该动态代理需要代理的对象 *@paramdelegate具体被代理的对象(实例) */ publicvoidsetDelegate(Objectdelegate); /** *获取通过该动态代理处理后的业务代理对象 *@return该代理处理后的代理业务对象 *@throwsSunnyException */ publicObjectgetProxy()throwsSunnyException; /** *设置该代理类需要处理的所有拦截器。 *@paraminterceptors拦截器集合 */ publicvoidsetInterceptors(Listinterceptors); } |
-----------------------------
Sunny目前提供了两种代理的实现方式:
1、基于Java的动态代理,原理大家可以到java.sun.com站点上去研究一番;
2、基于Cglib的字节码映射的方式,这点大家也可以关注Cglig来找到具体的答案。
需要说明的是,这两种代理各自有不同的应用域,某些情况是不能通用的。基于Java的动态代理要求被代理对象必须基于接口编程,即每个被代理对象有一个明确的接口。而基于Cglib的代理则不在此限制。
下面贴出源代码:
----------------------------------------
package
org.sunny.core.aop;
//import
java.lang.reflect.*;
import
org.sunny.exception.SunnyException;
import
org.sunny.cfg.PltMessage;
import
org.sunny.core.aop.interceptor.InterceptorUtil;
import
java.lang.reflect.InvocationHandler;
import
java.lang.reflect.Method;
import
java.util.List;
/**
*
采用Java动态代理的方式实现拦截器机制。
*
Copyright:
Copyright
(c)
2005
*
< p>Company:
Sunny虚拟开发组< /p>
*
@author
高雁冰({@link
mailto:haiger@163.com})
*
@version
1.0
*/
public
class
DynamicProxy
implements
AopProxy,InvocationHandler
{
privateObjectdelegate;//具体代理的业务逻辑对象 privateInterceptorUtilinterceptorUtil; /** *默认构造函数,由于该动态代理的实现需要通过Class.newInstance来调用(被框架),所以需要 *提供该默认构造函数,需要注意的是。在这之后,需要调用该类的setDelegate方法来具体设置该 *类具体代理哪个对象。 */ publicDynamicProxy() { //... } /** *IOC机制,通过运行时传入需要代理的业务逻辑对象。 *@paramdelegate需要代理的业务逻辑对象 */ publicDynamicProxy(Objectdelegate) { setDelegate(delegate); } /** *设置该动态代理需要代理的对象 *@paramdelegate具体被代理的对象(实例) */ publicvoidsetDelegate(Objectdelegate) { this.delegate=delegate; } /** *设置该代理类需要处理的所有拦截器。 *@paraminterceptors拦截器集合 */ publicvoidsetInterceptors(Listinterceptors) { interceptorUtil=newInterceptorUtil(interceptors); } /** *获取通过该动态代理处理后的业务代理对象 *@return该代理处理后的代理业务对象 *@throwsSunnyException */ publicObjectgetProxy()throwsSunnyException { if(null==delegate) { thrownewSunnyException(PltMessage.getInstance().getMessage( "BLA_IMPL_DELEGATE_NOT_SET")); } //构造该业务逻辑的包装类 Objectproxy=java.lang.reflect.Proxy.newProxyInstance( delegate.getClass().getClassLoader(), delegate.getClass().getInterfaces() ,this); returnproxy; } /** *拦截器的方法实现,该方法调用代理的业务逻辑的方法。 *@paramproxy被代理的类 *@parammethod被调用的业务方法 *@paramargs调用业务方法的输入参数 *@returnObject业务方法调用的返回值 *@throwsThrowable业务方法抛出的异常,该异常目前在外围系统去捕获的时候需要一些 *技巧,你应该这样(用getCause()方法)来捕获原始抛出的异常(范例代码) *< code> *< br>try *< br>{ *< br>... *< br>}catch(Throwabletb) *< br>{ *< br>System.out.println(tb.getCause().getMessage()); *< br>} *< /code>岁 */ publicObjectinvoke(Objectproxy,Methodmethod,Object[]args)throws Throwable { //调用所有的拦截器,对方法行为进行拦截操作 interceptorUtil.before(delegate,method,args); //具体业务逻辑方法的调用 Objectresult=null; try { result=method.invoke(delegate,args); }catch(Throwablee) { //对日志进行拦截操作 interceptorUtil.exception(delegate,method,args,e); } //业务逻辑调用完成,对结果进行拦截操作 interceptorUtil.after(delegate,method,args,result); returnresult; } }
|
---------------Cglib代理类--------------------
packageorg.sunny.core.aop;
importjava.lang.reflect.Method; importnet.sf.cglib.proxy.MethodInterceptor; importnet.sf.cglib.proxy.Enhancer; importnet.sf.cglib.proxy.MethodProxy; importorg.sunny.exception.SunnyException; importorg.sunny.cfg.PltMessage; importorg.sunny.core.aop.interceptor.InterceptorUtil; importjava.util.List; /** *采用Cglib代理的方式实现拦截器机制。需要注意的是: *由于目前EJB的实现方式是采用静态-动态Stub的实现。Cgblib在这种对象的代理生成上有一 *些问题,(EJB的Object的Stub是一个Finnal的类,不能完成代理),因此,如果系统采用EJB作为 *业务逻辑,则拦截器引擎只能使用: *< code> *org.sunny.blaccess.impl.DynanicProxyReactor *< /code> *Copyright:Copyright(c)2005 *< p>Company:Sunny虚拟开发组< /p> *@author高雁冰({@linkmailto:haiger@163.com}) *@version1.5 */
publicclassCglibProxyimplementsMethodInterceptor,AopProxy { privateObjectdelegate;//被代理的业务对象 privateEnhancerenhancer=newEnhancer(); privateInterceptorUtilinterceptorUtil; /** *设置该动态代理需要代理的对象 *@paramdelegate具体被代理的对象(实例) */ publicvoidsetDelegate(Objectdelegate) { this.delegate=delegate; } /** *设置该代理类需要处理的所有拦截器。 *@paraminterceptors拦截器集合 */ publicvoidsetInterceptors(Listinterceptors) { interceptorUtil=newInterceptorUtil(interceptors); } /** *获取通过该动态代理处理后的业务代理对象 *@return该代理处理后的代理业务对象 *@throwsSunnyException */ publicObjectgetProxy()throwsSunnyException { if(null==delegate) { thrownewSunnyException(PltMessage.getInstance().getMessage( "BLA_IMPL_DELEGATE_NOT_SET")); } if(-1!=delegate.getClass().getName().indexOf("$$")) { enhancer.setSuperclass(delegate.getClass().getSuperclass()); }else { enhancer.setSuperclass(delegate.getClass()); } enhancer.setCallback(this); returnenhancer.create(); } /** *实现对业务逻辑方法的具体拦截操作。在该操作里,可以在业务逻辑方法调用前后或者抛出异常的 *时候添加自己的控制,这里则选择执行系统配置的拦截器。 *@paramo被代理对象 *@parammethod访问的具体方法 *@paramargs方法输入参数 *@paramproxy方法代理 *@return方法执行结果 *@throwsjava.lang.Throwable */ publicObjectintercept(Objecto,Methodmethod,Object[]args,MethodProxyproxy) throwsThrowable { //调用所有的拦截器,对方法行为进行拦截操作 interceptorUtil.before(delegate,method,args); //具体业务逻辑方法的调用 Objectresult=null; try { result=proxy.invokeSuper(o,args); }catch(Throwablee) { //对日志进行拦截操作 interceptorUtil.exception(delegate,method,args,e); } //业务逻辑调用完成,对结果进行拦截操作 interceptorUtil.after(delegate,method,args,result); returnresult; }
|
posted on 2007-02-02 20:35
☜♥☞MengChuChen 阅读(276)
评论(0) 编辑 收藏 所属分类:
Spring