乐趣区

关于java:Java-方法代理实例操作静态代理JDK动态代理CGLIB动态代理

办法的代理能够在调用办法时进行其它的相干操作,并缩小代码的入侵和偶合。很多框架都用到了动静代理,并提供了减化代理操作,如:Spring 的 AOP。

动态代理

以电脑为模型,咱们都晓得,电脑是由 CPU、GPU、DISK 多个设施组装的,它们都是通过接口相连接。当初模仿一台电脑(Computer)通过接口设施(Device),代理(Proxy)组装不同的设施(CPU、GPU),并运行(run)。

接口设施Device

/*
 * File:Device.java
 * User:iChochy
 * URL:https://ichochy.com
 * Copyright (c) 2020
 * Date:2020/08/31 17:49:31
 */

package com.ichochy.proxy;

public interface Device {public void run();
}

设施 CPU

/*
 * File:CPU.java
 * User:iChochy
 * URL:https://ichochy.com
 * Copyright (c) 2020
 * Date:2020/08/31 17:52:31
 */

package com.ichochy.proxy;

public class CPU implements Device {


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

}

设施 GPU

/*
 * File:GPU.java
 * User:iChochy
 * URL:https://ichochy.com
 * Copyright (c) 2020
 * Date:2020/08/31 17:52:31
 */

package com.ichochy.proxy;

public class GPU implements Device {

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

}

电脑Computer

Computerstart 办法代理执行接口类办法

/*
 * File:SimpleProxy.java
 * User:iChochy
 * URL:https://ichochy.com
 * Copyright (c) 2020
 * Date:2020/08/31 17:54:31
 */

package com.ichochy.proxy;

public class Computer {

    private Device device;

    public Device start(){System.out.println("Start Computer");
        device.run();
        return device;
    }

    public Device getDevice() {return device;}

    public void setDevice(Device device) {this.device = device;}
}

运行电脑

通过类 Computerstart办法代理执行接口类办法

package com.ichochy;

import com.ichochy.proxy.CPU;
import com.ichochy.proxy.Computer;
import com.ichochy.proxy.GPU;

public class App {public static void main(String[] args) {Computer proxy = new Computer();
        proxy.setDevice(new CPU());
        proxy.start();
        proxy.setDevice(new GPU());
        proxy.start();}
}

运行状况

Start Computer
Game
Start Computer
Display

小结

动态代理能够代理某个办法,实现 AOP 操作,代理需要变更只需批改代理类,实现理解偶的成果。但不同的接口多个办法就要反复的编写代理类,来实现办法代理操作。

JDK 动静代理

实现接口 InvocationHandlerinvoke办法,通过 ProxynewProxyInstance办法,构建代理接口实例。相比动态代理更加灵便,动静代理不同的接口和接口中的办法。

改良电脑Computer

实现接口 InvocationHandlerinvoke办法,使用反射,动静执行代理办法

/*
 * File:SimpleProxy.java
 * User:iChochy
 * URL:https://ichochy.com
 * Copyright (c) 2020
 * Date:2020/08/31 17:54:31
 */

package com.ichochy.proxy;

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

public class Computer implements InvocationHandler {

    private Device device;

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {System.out.println("Start...");
        // 使用反射,动静执行代理办法,并返回办法执行后果
        Object result = method.invoke(device, args);
        System.out.println("End");
        return result;
    }

    public Device getDevice() {return device;}

    public void setDevice(Device device) {this.device = device;}


}

动静运行电脑

通过类 ProxynewProxyInstance办法构建代理接口类,实现办法的代理执行

/*
 * File:App.java
 * User:iChochy
 * URL:https://ichochy.com
 * Copyright (c) 2020
 * Date:2020/09/01 12:46:01
 */

package com.ichochy;

import com.ichochy.proxy.CPU;
import com.ichochy.proxy.Computer;
import com.ichochy.proxy.Device;

import java.lang.reflect.Proxy;

public class App {public static void main(String[] args) throws Exception {CPU cpu = new CPU();
        Computer computer = new Computer();
        computer.setDevice(cpu);
        // 获取代理接口实例
        Device device = (Device) Proxy.newProxyInstance(ClassLoader.getSystemClassLoader(), cpu.getClass().getInterfaces(), computer);
        device.run();}
}

运行状况

Start... 
Game
End

小结

使用反射,动静代理能够代理不同的接口的多个办法,不用批改代码。但只能用于接口办法的代理,无奈实现所有类办法。

CGLIB 动静代理

CGLIB 库是用于生成和转换 Java 字节码的高级 API,它容许运行时对字节码进行批改和动静生成,通过继承形式实现动静代理。

引入 CGLIB

通过 Maven 库治理引入第三方 CGLIB

<!-- https://mvnrepository.com/artifact/cglib/cglib -->
<dependency>
    <groupId>cglib</groupId>
    <artifactId>cglib</artifactId>
    <version>3.3.0</version>
</dependency>

改良电脑Computer

实现接口 MethodInterceptorintercept办法,使用反射,动静执行代理办法(原父类办法)

/*
 * File:SimpleProxy.java
 * User:iChochy
 * URL:https://ichochy.com
 * Copyright (c) 2020
 * Date:2020/08/31 17:54:31
 */

package com.ichochy.proxy;

import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;

import java.lang.reflect.Method;

public class Computer implements MethodInterceptor {

    @Override
    public Object intercept(Object obj, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {System.out.println("Start...");
        // 使用反射,动静执行代理办法,并返回办法执行后果
        Object result = methodProxy.invokeSuper(obj, args);
        System.out.println("End");
        return result;
    }
}

动静运行电脑

通过类 Enhancercreate办法构建代理类,实现办法的代理执行

/*
 * File:App.java
 * User:iChochy
 * URL:https://ichochy.com
 * Copyright (c) 2020
 * Date:2020/09/01 12:46:01
 */

package com.ichochy;

import com.ichochy.proxy.CPU;
import com.ichochy.proxy.Computer;
import net.sf.cglib.proxy.Enhancer;

public class App {public static void main(String[] args) throws Exception {Computer computer = new Computer();
        Enhancer enhancer = new Enhancer();
        // 设置要代理超类
        enhancer.setSuperclass(CPU.class);
        // 设置回调解决类
        enhancer.setCallback(computer);
        // 构建代理类
        CPU cpu = (CPU)enhancer.create();
        cpu.run();}
}

运行状况

Start... 
Game
End

小结

通过 CGLIB 库能够很不便的实现办法的动静代理,实现 AOP 操作。CGLIB库构建代理类的子类,并重写代理父类的办法,通过执行子类办法实现动静代理操作。

总结

当咱们要对一类办法或所有办法进行雷同操作时,使用办法代理能够很好实现咱们的需要,并不必去重写以前的业务办法,如:事务处理、日志监控、权限治理、异样捕获及解决。

总结:办法代理,实现 AOP 操作。

相干文章

  • Java 反射实例操作 2020/08/23

  • Java 中的重写 (Override) 与重载(Overload) 2020/08/20

  • 收费申请 JetBrains 开源开发许可证,蕴含 IDEA 2020/08/19

  • Java 开发环境的搭建,开启你的编程之旅 2020/08/15

源文:https://ichochy.com/posts/20200824/

退出移动版