AOP动态代理完整过程(超基础,超详细)

AOP

动态代理

租房的时候,房屋中介就是代理(筛选符合自己要求的房子,再供自己选择)。

  • 代理也需要和自己有相同的所有能力(自己有看房的能力,中介也有)。

  • 在程序中,代理是一个对象。这个对象由一个类产生,这个类本身就是动态产生。

  • 这个类本身不会被创建,在程序运行时动态产生。

  • InvocationHandler提供生成代理类的功能,InvocationHandler不是代理类,是帮助生成动态代理类的一个类。

代码分析

public class MyInvocationHandler implements InvocationHandler {
    //接收委托对象
    private Object object=null;

    //返回代理对象
    public Object bind(Object object){               //传入委托对象
        this.object=object;
        return Proxy.newProxyInstance(object.getClass().getClassLoader(),object.getClass().getInterfaces(),this);   
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println(method.getName()+"方法的参数是"+ Arrays.toString(args));
        Object result=method.invoke(this.object,args);
        System.out.println(method.getName()+"方法的结果是"+ result);
        return result;
    }
}

什么是委托对象,什么是代理对象

在租房过程中,“我”就是委托对象,“中介”就是代理对象。

具体工程中,计算器就是委托对象,打印日志对应工作的对象就是代理对象。

为什么要把委托对象传入代理对象中

因为要执行的业务方法要让本身执行。

为什么要返回代理对象

由MyInvocationHandler类创建一个动态代理类,再由动态代理类创建动态代理对象。

我们可以直接操作代理对象。

Proxy.newProxyInstance(object.getClass().getClassLoader(),object.getClass().getInterfaces(),this);

返回一个代理实例(代理对象),代理对象的创建需要类的支持,但这个类是动态创建的,所以要用类加载器添加进去。

Proxy.newProxyInstance 返回一个新的代理实例

object.getClass() 获取委托对象的运行实类

getClassLoader()获取类加载器

委托类的全部功能,代理类需全部拥有。

getInterfaces()获取实类中的所有接口

通过getInterfaces()将委托对象的所有接口交给代理类,代理类动态创建和委托对象功能一样的类。

this 通过MyInvocationHandler创建一个代理对象

invoke(Object proxy, Method method, Object[] args)

用于剥离核心业务代码和日志信息

method就是委托对象中核心业务的方法

method.getName() 拿到委托对象方法名。

args就是委托对象中核心业务的参数

Arrays.toString(args)把数组转化成字符串形式输出

Object result=method.invoke(this.object,args)

method.invoke为当前目标方法,invoke为通过反射机制调用。

代码分析

public class Test {
    public static void main(String[] args) {
        Cal cal=new CalImpl();
        MyInvocationHandler myInvocationHandler=new MyInvocationHandler();
        Cal cal1= (Cal) myInvocationHandler.bind(cal);
                cal1.add(3,3);
                cal1.div(3,3);
                cal1.sub(3,3);
                cal1.mul(3,3);
    }
}

Cal cal=new CalImpl()
MyInvocationHandler myInvocationHandler=new MyInvocationHandler()

创建对象

Cal cal1= (Cal) myInvocationHandler.bind(cal)

myInvocationHandler.bind(cal);通过myInvocationHandler中的bind方法,传入委托对象cal,会返回一个代理对象。

cal1.add(3,3)

调用代理对象,实现日志信息的插入与方法的实现。

程序执行完整流程

  • 首先实例化委托对象 Cal cal=new CalImpl(); (创建一个“我“)

  • MyInvocationHandler myInvocationHandler=new MyInvocationHandler(); (实例化InvocationHandler,通过InvocationHandler创建代理对象)

    Cal cal1= (Cal) myInvocationHandler.bind(cal);(”我“去买房,找了一个中介公司,中介公司派了一个人和我对接)

  • public Object bind(Object object)(记录委托对象)

    Proxy.newProxyInstance(object.getClass().getClassLoader(),object.getClass().getInterfaces(),this); (返回代理对象)

  • Cal cal1= (Cal) myInvocationHandler.bind(cal);(cal1就是创建好的代理对象,具备cal的所有功能)

  • cal1.add(3,3); (调用方法)

  • public Object invoke(Object proxy, Method method, Object[] args)(proxy就是cal1,method就是add,args就是3,3)

  • System.out.println(method.getName()+“方法的参数是”+ Arrays.toString(args));(add方法传入)

  • Object result=method.invoke(this.object,args);(由委托对象this.object调用方法)

©️2020 CSDN 皮肤主题: 1024 设计师:上身试试 返回首页