一、关于动态代理

1.什么是动态代理,有什么优势?

主要用来做方法的增强,让你可以在不修改源代码的情况下,增强一些方法,在方法执行前后做任何你想做的事情(甚至根本不去执行这个方法),因为在InvocationHandler的invoke方法中,你可以直接获取正在调用方法对应的Method对象,具体应用的话,比如可以添加调用日志,做事务控制等。动态代理是设计模式当中代理模式的一种。动态,指的是代理类是在程序运行时创建的,而不是在程序运行前手动编码来定义代理类的。这些动态代理类是在运行时候根据我们在JAVA代码中的“指示”动态生成的。相比于静态代理,动态代理的优势在于

  • 可以很方便的对代理类的方法进行统一处理。
  • 不用为每一个目标类(需要增强的类)单独编写代理类。

2.动态代理的原理

动态代理实现的原理实际由大体可以分为三步。后续我会专门写一篇博文,手动模拟下JDK动态代理,这里先记录一下

1、为目标类创建代理类的字节码文件。

2、使用ClassLoader将字节码文件加载到JVM。

3、创建代理类实例对象,执行对象的目标方法。

 

二、关于Proxy.newProxyInstance和InvocationHandler

1.newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h)

用于动态生成代理类。

参数:

  • loader: 类加载器
  • interfaces:动态代理类需要实现的接口
  • h:动态代理方法在执行时,会调用h里面的invoke方法去执行。

2.InvocationHandler

我们可以把InvocationHandler理解为对目标类进行增强,用来处理这些增强逻辑的类。

代理类会调用InvocationHandler的invoke()方法,执行增强逻辑。

invoke()方法参数:

  • proxy:就是代理对象,newProxyInstance()方法的返回对象
  • method:调用的方法
  • args: 方法中的参数

 

三、代码示例

接口:

public interface Car {
    void run(String speed);
}

 目标类(即需要被增强的类):

public class Benz implements Car{
    public void run(String speed) {
        System.out.println("奔驰车正在以 "+speed+"km/h的速度行驶中...");
    }
}

目标类的InvocationHandler:

public class BenzInvocationHandler implements InvocationHandler {
    Car target;

    public BenzInvocationHandler(Car target) {
        this.target = target;
    }

    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("打火,开始行驶");
        Object invoke = method.invoke(target, args);
        System.out.println("熄火,停车");
        return invoke;
    }
}

 测试类:

public class Test {
    public static void main(String[] args) {
        Car benz = new Benz();
        //生成目标类的代理类proxyBenz,对目标类做强的类
        Car proxyBenz = (Car) Proxy.newProxyInstance(benz.getClass().getClassLoader(),
                benz.getClass().getInterfaces(),
                new BenzInvocationHandler(benz));
        proxyBenz.run("80");
    }
}

运行结果:

打火,开始行驶
奔驰车正在以 80km/h的速度行驶中...
熄火,停车

 

Logo

瓜分20万奖金 获得内推名额 丰厚实物奖励 易参与易上手

更多推荐