AOP-动态代理

动态代理的原理
代理设计模式的原理:使用一个代理将原本对象包装起来,然后用该代理对象”取代”原始对象。任何对原始对象的调用都要通过代理。代理对象决定是否以及何时将方法调用转到原始对象上。

代理模式:可以理解为有两个对象,代理对象和目标对象,代理对象就是帮助我们完成这件事的对象,目标对象就是我们要去做的事情。动态代理就是无论目标对象是什么,都可以通过这样的一个类,去动态生成相对应的代理对象,帮助去完成相应的功能。更像是一个工具类,在任何情况下去生成一个代理对象。

代理对象生成以后,为什么也能帮助我们去实现最终的功能?

①代理对象知道要实现什么功能。②代理对象对接口中的抽象方法的实现,可以利用InvocationHandler来控制代理对象对功能的实现过程。

动态代理的方式
  1) 基于接口实现动态代理: JDK动态代理
  2) 基于继承实现动态代理: Cglib、Javassist动态代理

package com.atguigu.proxy;

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

public class ProxyUtil {

    private MathImpl mathImpl;//目标对象,其实应该是Object
    
    public Object getProxy() {
        ClassLoader loader = this.getClass().getClassLoader();//类的加载器,创建一个代理类,动态生成一个动态代理类,执行就需要加载,需要指定一个类加载器
        Class[] interfaces = mathImpl.getClass().getInterfaces();//目标对象都有那些方法,代理对象通过获取其实现的接口确定,所以代理对象会和目标对象一样实现相同的接口
        return Proxy.newProxyInstance(loader, interfaces, new InvocationHandler() {//第三个参数:代理对象如何实现目标对象的方法
            //Java中的所有生成的动态代理类都继承于Proxy类
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                return method.invoke(mathImpl, args);//代理模式原则要保证结果的一致性,可以让代理对象调用目标对象的方法就可以保证一致性
            }
        });
    }
    
}

实现对计算器的动态代理:

package com.atguigu.proxy;

import java.util.Properties;

public class Test {

    public static void main(String[] args) {
        
        /*MathI math = new MathImpl();
        int result = math.div(1, 1);
        System.out.println(result);*/
        
        ProxyUtil proxy = new ProxyUtil(new MathImpl());
        MathI math = (MathI)proxy.getProxy();  //注意不能使用目标对象类型,因为目标类可能还有接口标准之外的方法,所以要强转为接口变量引用
        int i = math.div(4, 1);
        System.out.println(i);
        
    }
    
}
package com.atguigu.proxy;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.Arrays;

public class ProxyUtil {

    private MathImpl mathImpl;   //实际中采用Object类型
    
    
    
    public ProxyUtil(MathImpl mathImpl) {
        super();
        this.mathImpl = mathImpl;
    }



    public Object getProxy() {
        //获取当前类的类加载器,用来加载代理对象所属类
        ClassLoader loader = this.getClass().getClassLoader();
        //获取目标对象实现的所有接口的Class,代理类回合目标类实现相同的接口,最终通过代理对象实现功能
        Class[] interfaces = mathImpl.getClass().getInterfaces();
                
        return Proxy.newProxyInstance(loader, interfaces, new InvocationHandler() {
            
            //代理对象实现功能的方式
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                // TODO Auto-generated method stub
                try {
                    MyLogger.before(method.getName(), Arrays.toString(args));
                    Object result = method.invoke(mathImpl, args);//动态代理对象实现功能
                    MyLogger.after(method.getName(), result);
                    return result;
                } catch (Exception e) {
                    // TODO: handle exception
                    MyLogger.throwing();
                    e.printStackTrace();
                } finally {
                    System.out.println("哪都有我");
                }
                return null;
            }
        });
    }
    
}
package com.atguigu.proxy;

public interface MathI {

    int add(int i, int j);
    int sub(int i, int j);
    int mul(int i, int j);
    int div(int i, int j);
    
}
interface MathI
package com.atguigu.proxy;

public class MathImpl implements MathI {

    @Override
    public int add(int i, int j) {
        int result = i + j;
        return result;
    }

    @Override
    public int sub(int i, int j) {
        int result = i - j;
        return result;
    }

    @Override
    public int mul(int i, int j) {
        int result = i * j;
        return result;
    }

    @Override
    public int div(int i, int j) {
        int result = i / j;
        return result;
    }

    
    
}
MathImpl
package com.atguigu.proxy;

public class MyLogger {

    public static void before(String methodName, String args) {
        System.out.println("method:"+methodName+",arguments:"+args);
    }
    
    public static void after(String methodName, Object reslut) {
        System.out.println("method:"+methodName+",reslut:"+reslut);
    }
    
    public static void throwing() {
        System.out.println("有异常了。。。。");
    }
    
}
MyLogger
原文地址:https://www.cnblogs.com/lemonzhang/p/12907886.html