`
huangshihang
  • 浏览: 11514 次
社区版块
存档分类
最新评论

《架构探险》之面向切面编程(AOP)(上)

阅读更多

写代码应该是一个由繁到简,然后由简到繁的一个螺旋上升的过程。

 

        在Spring中有个很重要的特性那就是面向切面编程(AOP)。假想这样的一个情景,如果有一段逻辑很多方法执行前或执行后都需要,我们会怎么办?我们试着从一个极端走到另一个极端来考虑这个问题。从一个极端出发,如果需要这段逻辑的方法个数很少只有一个,我们可以直接在方面的最前面或最后面调用这段逻辑,怎么简单怎么来,像这样:

public void function(){
    commonBegin();
    ...
    commonEnd();
}

         当这样的方法从一个变成两三个的时候,我们就看到了两三个类似的方法,然后当方法数变得特别多的时候,我们就会看到一堆这样的方法,当不只有一个Begin或End,而是还包含其他的Begin和End时,随着代码的不断增多,代码看起来估计就像套马杆的汉子般威武雄壮了...

        那怎样才能把这样的问题搞的简单点呢?找代理~

        1、静态代理:

        首先我们可以尝试一下找个静态代理,静态代理就是谁是谁的代理都已经很明显了,一对一的服务,像这个样子(举个例子,你的一序列的方法都属于一些顾客的行为):

public class Proxy implements Cliemt{    
    private Client client;  //Client只是其中的一个顾客类
    public Proxy(Client client){
        this.client = client; 
   }
    public void buy(){
        doSomething();
        client.buy();    //顾客的工作就是买买买
    }
}

         这样的话,顾客方法里面就不需要写那些前置或者后置的逻辑,代理里面来实现这部分就可以了,保证了顾客清清白白,然而,然而,这样不就凭空多了跟顾客类一样多的代理类了吗,代码不仅没有减少,反而翻番了。

       2、JDK动态代理:

        静态代理不行,那就找动态代理。动态代理会根据你的类生产对应的代理类,首先看看JDK的动态代理的实现机制。在静态代理中,有多少类需要实现同一个共同逻辑就需要对应多少个静态代理类,如果代理类中的代理对象类型没有指定的话,即前面没有指定ClientImpl,那么可以抽象出一个代理的调用控制器,在控制器中通过反射机制来调用具体对象的方法:

public class DynamicInvocationHandler implements InvocationHandler{
     private Object object;
     public DynamicInvocationHandler (Object object){
         this.object = object;
     }

     public Object invoke(Object proxy, Method method, Object... params){
         return method.invoke(object, params);  // try
     }
}

         然后我们可以通过Java中的Proxy根据我们的调用控制器来动态生成我们的代理:

Client client= new ClientImpl();
DynamicInvocationHandler handler = new DynamicInvocationHandler (client);
Client clientProxy = (Client ) Proxy.newInstance(client.getClass().getClassLoader(), client             .getClass().getInterfaces(), handler);

         3、CGLIB动态代理:

        JDK动态代理需要类实现相应的接口,如果是针对没有接口的类,可以使用CGlib来实现,实现方式大概是这个样子:

public class CGLibInterceptor implements MethodInterceptor{
     public Object intercept(Object object, Method method, Object... params, MethodProxy proxy){
         return proxy.invokeSuper(object, params);  // try
     }
}

         然后可以通过Enhance的create方法创建代理对象:

CGLibInterceptor cglibInterceptor = new CGLibInterceptor();
Hello helloProxy = (Hello)Enhancer.create(Hello.class, cglibInterceptor);
helloProxy.say("````");

          有了动态代理之后,当我们对某个类的方法前或之后调用特定的逻辑时,就可以创建一个动态的代理对象出来,特定的逻辑放在InvocationHandler或MethodInterceptor中,可以把这两个类看成是动态代理的中介,有了这个中介之后,不管什么类都可以根据需要创建出对应的动态代理,省去了编写一堆静态代理的麻烦,而这个中介中的特定逻辑其实就是AOP的中切面(待续~)

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics