您的位置:首页 > 编程语言

自行打造实现控制反转容器(IOC)与面向方面编程(AOP)的轻量级Framework(3)

2008-09-17 12:42 726 查看
MyFrameworkAOP部分
原创: 牛超  TOKYO
 
旨于搭建轻量架构,为目标对象设置装备与拦截器,并利用代理模式封装对象,其中如何拦截对象的方法行为并将装备置于其中尤为关键,具体实现即拦截器类,代码如下所示:
package myFramework;
 
import java.lang.reflect.* ;
/**
 * ProxyObjectHandler : Proxy Object Handler
 * create proxy objects according to target object and it's advices
 *
 * @author Niu Chao
 * @since 2008-8-19
 * @version 0.1
 */
public class ProxyObjectHandler extends ProxyTargetHandler
{
        private IAdvice[] advices ;
        private Reflection reflect ;
       
        //construct the proxy according to proxy target and advices
        //根据目标 ?象与装备 ?建对 象
        public ProxyObjectHandler(Object objproxy , IAdvice[] aAdvs)
        {
                 super(objproxy) ;
                 reflect = Reflection.getInstance() ;
                 setAdvices(aAdvs) ;
                 sortAdvices() ;
        }
        public Object getProxyObject()
        {
                 return Proxy.newProxyInstance(
                 this.getObjTarget().getClass().getClassLoader(), this.getObjTarget()
                 .getClass().getInterfaces(), this);
        }
        //get the number of advice by sort .
        //将装备 按指定方式编 号
        private int adviceSortNumber(IAdvice adv)
        {
                 Class cls = adv.getClass() ;
                 try
                 {
                           //IBeforeAdvice
                           if ( reflect.isAssignable("myFramework.IBeforeAdvice",cls))
                           {
                                    return 0 ;
                           }//IAroundAdvice
                           else if (reflect.isAssignable("myFramework.IAroundAdvice",cls))
                           {
                                    return 1 ;
                           }//IThrowsAdvice
                           else if (reflect.isAssignable("myFramework.IThrowsAdvice",cls))
                           {
                                    return 2 ;
                           }
                           else //Class.forName("myFramework.IAfterAdvice").isAssignableFrom(adv.getClass())
                           {
                                    return 3 ;
                           }
                 }
                 catch(Exception ex)        
                 {
                           ex.printStackTrace() ;
                           System.exit(-1) ;
                           return -1 ;
                 }
        }
       
        //sort the advices
        //以编 号为 ?先级 排序装备
private void sortAdvices()
        {
                 IAdvice advref ;
                 if (advices.length < 1)
                           return ;
                 for ( int i = 0 ; i < advices.length - 1 ; i ++ )
                 {
                           for ( int j = i + 1 ; j < advices.length ; j ++)
                           {
                                    if (adviceSortNumber(advices[i]) > adviceSortNumber(advices[j]))
                                    {
                                             advref = advices[i] ;
                                             advices[i] = advices[j] ;
                                             advices[j] = advref ;
                                    }
                           }
                 }
        }
       
        //getter
        public IAdvice[] getAdvices()
        {
                 return advices ;
        }
        //setter
        public void setAdvices(IAdvice[] advs)
        {
                 advices = advs ;
        }
       
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable
        {
                 // TODO: Add your code here
                 int i = 0 , j = 0 , iSortnum;
                 IAdvice advref ;
                 Reflection reflect = Reflection.getInstance() ;
                
                 //arguments of advice
                 Object[] advArgs ;
                 Object result = null;
                
                 //process advices with before function
                 //处理带 有前置切入点的装备                   
for (i = 0 ; i < advices.length ; i ++)
                 {
                           iSortnum = adviceSortNumber(advices[i]) ;
                           if ( iSortnum < 2)
                           {
                                    //record the start index of aroundadvices
                                    //记 ?AROUND装备 索引号以备 后用
                                    if (iSortnum < 1)
                                    {
                                             j = i ;
                                    }
                                    advArgs = new Object[]{this.getObjTarget() , method , args};
                                    //invoke the function called "before" of device
                                    //调用装备 的前置切入处 理方法
                                    reflect.invokeMethod(advices[i], "before", advArgs) ;
                           }
                           else
                           {
                                    break ;
                           }
                 }
                
            //process the proxy with ThrowAdvice set up.
                 //处理异 常处 理装备                
try
                 {
                           //process the proxy function                           
                           //调用目标 ?象的方法
                           result = method.invoke(this.getObjTarget(), args);
                 }
                catch(InvocationTargetException ex)
                {
                        boolean bflagthrow = true ;
                        //catch exception and active thowadvices
                        for ( ; i < advices.length ; i ++)
                        {
                                iSortnum = adviceSortNumber(advices[i]) ;
                                if (iSortnum == 2) //ThrowAdvice
                                {
                                        advArgs = new Object[]{this.getObjTarget() , method , args ,ex.getTargetException()};
                                        reflect.invokeMethod(advices[i], "afterThrowing", advArgs) ;
                                        bflagthrow = false ;
                                }
                                else
                                {
                                        break ;
                                }      
                        }
                        if (bflagthrow)
                        {
                                throw ex.getTargetException();
                        }                      
               }                 
//process advices with afterReturn function
                 //调用各装备 的后置处 理
                 for (i = j + 1; i < advices.length ; i ++)
                 {
                           iSortnum = adviceSortNumber(advices[i]) ;
                           if (iSortnum != 2)
                           {
                                    advArgs = new Object[]{this.getObjTarget() , method , args ,result};
                                    reflect.invokeMethod(advices[i], "afterReturn", advArgs) ;
                           }
                 }
                
                 return result ;                               
        }       
 
}
拦截器通过切入点可以灵活的实现加载装备的所有功能,而装备的定义正是面向方面的体现,各个装备专注于自己的方面比如日志、权限验证等,提高了可重用性。至于装备接口的定义,这里只举一个例子,与Spring不同,IAroundAdvice即对象包围处理装备。
package myFramework;
import java.lang.reflect.Method;
 
/**
 * IAroundAdvice : Around Advice Interface
 * handle a method and process before/after(around) it.
 * @author Niu Chao
 * @since 2008-8-19
 * @version 0.1
 */
public interface IAroundAdvice  extends IAdvice
{
       public void before(Object target, Method m, Object[] args) ;
       public void afterReturn(Object target, Method m, Object[] args,
                               Object objReturn);
}
正如定义的那样,该装备的实例对象必须实现两个函数before与afterReturn。恰似结合了BEFORE与AFTER两种装备那样。这些装备与目标实例的结合不是直接耦合作用的,而利用IoC和代理模式实现了松散耦合,并且分工明确,系统开发也会变得更为自自由由。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
相关文章推荐