java动态代理和aop的对应关系

   昨天介绍了下httpclient,其中涉及到aop的使用,其实aop的底层是用java动态代理实现的。动态代理其实就是用java.lang.reflect.InvocationHandler和java.lang.reflect.Proxy进行操做,
这个使用也是比较简单的,记得一年前我刚开始学Java的时候,这个是我最难理解的。其实动态代理是在运行时创建代理对象,从而在实际调用方法(通过反射)的各个时机进行各种操作。

      首先要实现InvocationHandler这个接口,具体代码如下,解析放到注释中:

   

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;

/**
 * 动态代理首先要实现InvocationHandler这个接口
 * 
 */

public class MyInvokeHandler  implements InvocationHandler {
    //实际被代理的对象
    private Object object;

    public MyInvokeHandler(Object object){
        this.object = object;
    }

    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        /**
         * 这里可以在调用方法的各个时机,进行各种操作,
         * 其实对应也对应aop的各个通知。其实这里还可以
         * 有异常处理,在完善代码时给出。
         */
        System.out.println("调用方法之前");
        Object obj = method.invoke(object,args);
        System.out.println("调用方法之后");
        //返回相应的结果,这里可以偷梁换柱,把结果换掉。
        return obj;
    }
}

    实际对象对应的类:

 

//注意这两个类不是在同一个文件的,我这里是为了方便
//因为java中一个文件不能有两个public类


public interface JayChouConcert {
    String singing(String musiceName);
    void dancing();
}


public class OpenJayChouConcert implements JayChouConcert {

    public String singing(String musiceName) {
        System.out.println(String.format("周杰伦唱%s。。。",musiceName));
        return musiceName;
    }

    public void dancing() {
        System.out.println("伴舞。。。");
    }
}

 测试上述的代码:

 

import java.lang.reflect.Proxy;

public class Test {
    public final  static void  main(String[] args){
        //实际要代理的对象
        JayChouConcert jayChouConcert = new OpenJayChouConcert();

        MyInvokeHandler myInvokeHandler = new MyInvokeHandler(jayChouConcert);
        //使用Proxy的newProxyInstance方法创建代理对象
        JayChouConcert jayChouConcert1 = (JayChouConcert)Proxy.newProxyInstance(jayChouConcert.getClass().getClassLoader()
                ,jayChouConcert.getClass().getInterfaces(),myInvokeHandler);
        jayChouConcert1.singing("蒲公英的约定");
    }
}

运行输出的结果为:

调用方法之前
周杰伦唱蒲公英的约定。。。
调用方法之后
 

上述的代码便是动态代理的helloworld,接下来讲讲动态代理有什么用和springboot的aop中各种通知的对应关系。

动态代理因为在使用反射调用实际的方法前,可以进行相关的处理。

比如说:你有100个方法都要打印一条相同的信息,你不可能在100个方法前都加那个信息,因为某一天你要修改这条信息了,

你就要修改100边,而用动态代理的话你可以怎么做呢?

假设就上述的两个方法,我都要加一句话:最美的不是下雨天,而是与你躲过雨的屋檐。

你可以选择每次调用方法的时候都加,不过可能你某天要变成:而我已经分不清,你是友情还是错过的爱情。

那么你就要改两遍,这还好,如果是100方法的话,就麻烦了,而且还很容易出错,指不定你哪句话改错了。

    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        /**
         * 这里可以在调用方法的各个时机,进行各种操作,
         * 其实对应也对应aop的各个通知。其实这里还可以
         * 有异常处理,在完善代码时给出。
         */
        System.out.println("最美的不过下雨天,而是与你躲过雨的屋檐。");
        Object obj = method.invoke(object,args);
        System.out.println("而我已经分不清,你是友情还是错过的爱情。");
        return obj;
    }
  }

调用结果为:

最美的不过下雨天,而是与你躲过雨的屋檐。
周杰伦唱蒲公英的约定。。。
而我已经分不清,你是友情还是错过的爱情。

这只是其中一种运用,还有很多,你可能要对方法返回的结果,或者这个方法调用出现异常的时候进行相关的处理。这些处理

的时机就对应aop中的各种通知了。代码如下:

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;

/**
 * 动态代理首先要实现InvocationHandler这个接口
 *
 */

public class MyInvokeHandler  implements InvocationHandler {
    //实际被代理的对象
    private Object object;

    public MyInvokeHandler(Object object){
        this.object = object;
    }

    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        /**
         * 这里可以在调用方法的各个时机,进行各种操作,
         * 其实对应也对应aop的各个通知。其实这里还可以
         * 有异常处理,在完善代码时给出。
         */
        try{
            //下面的System.out.println其实用方法表示更好,
            //就是在调用实际方法的各个时机,调用其它方法
            System.out.println("前置通知。。。@Before");

            Object obj = method.invoke(object,args);
            
           
            return obj;
        }catch (Exception e){
            System.out.println("后置异常通知。。。 @AfterThrowing");
        }finally {
            System.out.println("后置返回通知。。。 @AfterRuturning,从这个位置可以拿到返回结果obj");
        }
        return null;
    }

     //System.out.println("后置最终通知。。。@After,finally退出后执行,这个不管是否异常都会会 
     //执行");
}

进行测试:

方法正常运行的时候:

前置通知。。。@Before
周杰伦唱蒲公英的约定。。。
后置返回通知。。。 @AfterRuturning,从这个位置可以拿到返回结果obj

//这里还有After的结果,暂时无法演示

这这里可以看到异常的通知没有执行。

在方法中加入异常代码:

public class OpenJayChouConcert implements JayChouConcert {

    public String singing(String musiceName) {
        System.out.println(String.format("周杰伦唱%s。。。",musiceName));
        int i = 10;
        i = i/0;
        return musiceName;
    }

    public void dancing() {
        System.out.println("伴舞。。。");
    }
}

此时运行:

前置通知。。。@Before
周杰伦唱蒲公英的约定。。。
后置异常通知。。。 @AfterThrowing
后置返回通知。。。 @AfterRuturning,从这个位置可以拿到返回结果obj

//这里还有After的结果,暂时无法演示
下次在Springboot环境实际操作下的aop。

 

你可能感兴趣的:(java动态代理和aop的对应关系)