动态代理解析

什么是动态代理

要知道什么是动态代理,相对的,我们首先要了解什么是静态代理,

静态代理解析连接https://blog.youkuaiyun.com/qq_42051306/article/details/114107743

从静态代理我们知道,代理的功能主要有两点:

1. 隐藏我们需要代理的类(也就是原有的类,需要去代理的类,叫做被代理类)

2. 既然要隐藏我们的被代理类,就不能去改变原有类的代码,在此基础上,通过代理我们还可以添加其他功能,叫做功能增强

静态代理实现了代理的功能,下面我们需要的动态代理是为了改进静态代理的缺点

动态代理是在运行时动态生成的,即编译完成后没有实际的class文件,而是在运行时动态生成类字节码,并加载到JVM中

我们依然通过代码来了解动态代理的一个过程,既然是代理,那么我们依然采用JDK动态代理方式,接口、类的形式

主题接口

public interface UserDao {
    void add();
}

实现类

public class UserDaoImpl implements UserDao{

    @Override
    public void add() {
        System.out.println("add...");
    }

}

注意这里就没有像动态代理一样的代理类了,因为我们的代理类是通过Java反射的方式来生成,是动态获取

public class Test {
    public static void main(String[] args) {
        UserDaoImpl user = new UserDaoImpl();
        UserDao instance = (UserDao) getProxyInstance(user);
        instance.add();
    }

    public static Object getProxyInstance(Object obj){
        MyInvocationHandler handler = new MyInvocationHandler();
        handler.bind(obj);
        return Proxy.newProxyInstance(obj.getClass().getClassLoader(), obj.getClass().getInterfaces(), handler);
    }
}

创建动态代理对象的主要过程是使用Proxy类中的newProxyInstance()方法

该方法有三个参数

第一个叫做类加载器:

这个参数我们在调用的时候应该怎么填?--------由于代理类是需要去代理原有的类的,因此类加载器也应该和原有类的类加载器相同

因此在原有对象的基础上通过反射得到类加载器填入第一个参数user.getClass().getClassLoader()

第二个参数叫做接口:

由于类可以实现多个接口,因此这个参数是一个数组类型,此处的接口就是我们原有类实现的接口

也是通过对象通过反射的方式获取原有类实现的接口user.getClass().getInterfaces()

第三个参数叫做处理者:

这是最关键的一个参数,通过文档我们可以看到这个参数需要一个InvocationHandler的对象

既然没有就需要创建一个对象,而又发现InvocationHandler是个接口,因此我们需要自己创建这个接口的一个实现类

class MyInvocationHandler implements InvocationHandler{

    private Object obj;
     public void bind(Object obj){
         this.obj = obj;
     }
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("增强之前");
        Object o = method.invoke(obj, args);
        System.out.println("增强之后");
        return o;
    }
}

通过这个实现类来创建一个对象,实现里面的一个抽象方法invoke();

这个方法就是代理的主要方法,当我们通过newProxyInstance()方法创建的代理类调用原有的add方法时,就会自动的调用invoke()方法

怎么通过这个方法来调用原有的add方法呢,我们可以看到在invoke方法中有三个参数

第一个参数proxy:

这个参数其实就是我们产生的代理对象,其实在平时的使用中,这个参数基本上使用不到,关于参数详情请看https://blog.youkuaiyun.com/yaomingyang/article/details/81040390

第二个参数method:

这个参数其实就是我们要增强的方法,也就是需要代理类去调用的方法,通过这个参数调用invoke()方法

method.invoke(Object obj, Object... args)

这个方法有两个参数需要 填写,

1. 第一个参数就是我们需要代理的类的对象,

定义为private Object obj;

创建bindf()方法为该属性赋值,调用的时候传入一个真正的对象即可,

2. 第二个参数就是我们需要调用的方法的参数,是个可变形参,根据实际方法的参数来确定,invoke()方法中的第三个参数(注意这里的两个invoke()并不相同)

最后结果可以为

希望对动态代理不熟悉的人有所帮助

 

 

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值