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

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);

}

正如定义的那样,该装备的实例对象必须实现两个函数beforeafterReturn。恰似结合了BEFOREAFTER两种装备那样。这些装备与目标实例的结合不是直接耦合作用的,而利用IoC和代理模式实现了松散耦合,并且分工明确,系统开发也会变得更为自自由由。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值