办法的代理能够在调用办法时进行其它的相干操作,并缩小代码的入侵和偶合。很多框架都用到了动静代理,并提供了减化代理操作,如: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
Computer
的start
办法代理执行接口类办法
/* * 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; }}
运行电脑
通过类Computer
的start
办法代理执行接口类办法
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 ComputerGameStart ComputerDisplay
小结
动态代理能够代理某个办法,实现AOP
操作,代理需要变更只需批改代理类,实现理解偶的成果。但不同的接口多个办法就要反复的编写代理类,来实现办法代理操作。
JDK动静代理
实现接口InvocationHandler
的invoke
办法,通过Proxy
的newProxyInstance
办法,构建代理接口实例。相比动态代理更加灵便,动静代理不同的接口和接口中的办法。
改良电脑Computer
实现接口InvocationHandler
的invoke
办法,使用反射,动静执行代理办法
/* * 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; }}
动静运行电脑
通过类Proxy
的newProxyInstance
办法构建代理接口类,实现办法的代理执行
/* * 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... GameEnd
小结
使用反射,动静代理能够代理不同的接口的多个办法,不用批改代码。但只能用于接口办法的代理,无奈实现所有类办法。
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
实现接口MethodInterceptor
的intercept
办法,使用反射,动静执行代理办法(原父类办法)
/* * 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; }}
动静运行电脑
通过类Enhancer
的create
办法构建代理类,实现办法的代理执行
/* * 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... GameEnd
小结
通过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/