spring5 入门(五)动态代理原理

知乎上有一篇极为详细讲解文章!

https://www.zhihu.com/question/20794107/answer/658139129

 

动态代理分为两大类:

基于接口的动态代理---JDK动态代理

基于类的动态代理--cglib

这里讲的是JDK动态代理,基于接口的。

 

静态代理时需要我们对每一个类都生成一个代理类,这样代码量及翻倍,且类一旦多起来极其麻烦,这时候需要动态的生成代理对象。

首先需要注意的new关键字,生成一个实例背后,是由一个class对象的。

一个class对象包含了类的所有信息

这时候我们就可以不写代理类,而是通过代理class对象,从而生成一个实例(反射)

这样我们通过传入目标对象,通过目标对象的getclass,就可以动态创建代理对象了

jdk动态代理是基于接口,这时候需要目标类实现一个或一组接口,通过传入这个目标对象的接口(target.getClass().getInterfaces()),来创建代理类实例

JDK提供了一个Proxy类,用来创建代理类实例的,直接使用静态方法newProxyInstance,分别传入此类的加载器,目标类的接口信息,以及InvocationHandler.class

 

    public Object getProxy(){
        return Proxy.newProxyInstance(this.getClass().getClassLoader(), target.getClass().getInterfaces(),InvocationHandler.class);
    }

 

由于接口是无法构建实例,所以传入这个参数InvocationHandler.class

InvocationHandler接口是proxy代理实例的调用处理程序实现的一个接口,每一个proxy代理实例都有一个关联的调用处理程序;在代理实例调用方法时,方法调用被编码分派到调用处理程序的invoke方法

InvocationHandler这是个接口需要重写invoke方法,proxy对应上面生成代理类,method对应接口方法,args代表的方法参数

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        Object invoke = method.invoke(target, args);
        return invoke;
    }

完整代码和测试代码如下,new一个代理类,通过set传入目标类,由于都是实现同一组接口,需要进行接口类强转,在执行接口对应的方法,所以局限就是需要实现接口,且只能代理接口的方法

package com.hys.proxy;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
//动态生成代理类
public class myproxy implements InvocationHandler {
    private Object target;

    public void setTarget(Object target) {
        this.target = target;
    }

    public Object getProxy(){
        return Proxy.newProxyInstance(this.getClass().getClassLoader(), target.getClass().getInterfaces(),this);
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        Object invoke = method.invoke(target, args);
        return invoke;
    }
  //测试代码
    public static void main(String[] args) {
        host host = new host();
        myproxy mx = new myproxy();
        mx.setTarget(host);
        rent proxy = (rent) mx.getProxy();
        proxy.rent();
    }
}

执行过程如下,会先执行重写的invoke方法,在执行对应接口的方法,即上面对面Object invoke = method.invoke(target, args)这一步,所以可以在invoke里执行自己需要代码。

 

 

spring5 入门(五)动态代理原理

 

 

 

 

spring5 入门(五)动态代理原理

上一篇:npm install 报错 cb.apply is not a function


下一篇:Windows | 电脑开机,出现UEFI BIOS Utility-EZ Mode 什么原因呢,不能正常启动