【永恒的瞬间】
☜Give me hapy ☞

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

只有注册用户登录后才能发表评论。


网站导航: