Spring AOP的实现机制

Spring AOP属于第二代AOP,采用动态代理机制(Dynamic Proxy)和字节码生成技术(Code Generation Library)实现。这两种方法都是在运行期间为代理目标对象生成一个代理对象,而将横切逻辑植入到这个代理对象当中,系统最终使用的是植入了横切逻辑的代理对象,而不是真正的目标对象。

    代理机制的实现已经有现成的设计模式支持,叫代理模式(Proxy Pattern)。在代理模式中,通常涉及4种角色。

1.接口:该接口是对被访问者或被访问资源的抽象。在严格的设计模式中,这样的抽象接口是必须的,但某些场景下不使  用类似的统一抽象接口也是可以的。

2.具体实现类:就是具体实现类嘛。

3.代理实现类:该类持有一个接口类的具体实例。

4.客户端:代表访问者的抽象角色,他将会访问接口类的对象或资源。

    对于动态代理的实现主要由一个类和一个接口组成,即java.lang.reflect.Proxy类和java.lang.reflect.InvocationHandler接口。具体实现方法这里就不过多赘述了。不太明白的话参考一下Javadoc。Java Reflection In Action(Manning, 2005)一书对Java的Reflection机制进行了详尽的阐述,其中有一章专门讲解了动态代理机制,不妨一读。

    对于Spring AOP来说,如果发现代理目标对象实现了相应的接口,则采用动态代理机制为其生成代理对象实例。而如果代理目标对象没有实现任何接口,Spring AOP会尝试使用一个称为CGLIB(Code Generation Library)的开源的动态字节码生成类库,为目标生成动态的代理对象实例。其原理是,我们可以对目标对象进行继承扩展,为其生成相应的子类,而子类可以通过覆写来扩展父类的行为,只要将横切逻辑的实现放到子类中,然后让系统使用扩展后的目标对象的子类,就可以达到与代理模式相同的效果了。但是,使用继承的方式来扩展对象定义,也不能像静态代理模式那样,为每个不同的类型的目标对象都单独创建相应的子类。所以,我们要使用CGLIB在系统运行期间动态的为目标对象生成相应的扩展子类。

    为了演示CGLIB的使用,我们定义的目标类如下所示:

     public class Requestable{

       public void request(){

    System.out.println("rq in Requestable without implement any interface");

    }

     }


      要对上面的类进行扩展,首先需要实现一个net.sf.cglib.proxy.Callback。不过更多的时候,我们会直接使用net.sf.cglib.proxy.MethodInterceptor接口,因为它扩展了Callback接口。下面我们实现Callback。

      public class RequestCtrlCallback implements MethodInterceptor {

    private static final Log logger = LogFactory.getLog(RequestCtrlCallback.class);

    public Object interceptor(Object obj, Method method, Object[] args, MethodProxy proxy) throw throwable {

      System.out.println("this is before " + method);

      proxy.invokeSuper(obj, args);

      System.out.println("this is before " + method);

      return null;

    }

  }

这样我们就实现了对request()方法请求进行访问控制的逻辑。现在我们要通过CGLIB的Enhancer为目标对象生成一个子类,并将RequestCtrlCallback中的横切逻辑附加到该子类中,代码如下:

  Enhancer enhancer = new Enhancer();

  enhancer.setSuperclass(Requestable.class);

  enhancer.setCallback(new RequestCtrlCallback());

  

  Requestable proxy = (Requestable) enhancer.create();

  proxy.request();

通过为Enhancer指定需要生成的子类对应的父类,以及实现Callback,Enhancer最终为我们生成了需要的代理对象实例。

另外,使用CGLIB对象进行扩展的唯一限制就是无法对final方法进行覆写。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值