需求:增强未知方法的代码
简单方案:继承或者聚合
-
继承,调用方法前后加增强逻辑
-
聚合 - 静态代理
-
持有被代理类对象 或者接口
-
可通过嵌套实现代理的组合 和 装饰器模式很像
-
高级方案
- 代理所有的类,不只是某一类的接口,静态的聚合方式成员属性是具体的
JDK 动态代理
package club.interview.design_pattern.chapt6_proxy; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; /** * @author QuCheng on 2020/6/15. */ public interface Vegetable { void growUp(); class Cabbage implements Vegetable { @Override public void growUp() { System.out.println("卷心菜慢慢长大"); } } class LogProxy implements InvocationHandler { Object o; public LogProxy(Object o) { this.o = o; } public static Object getProxy(Object object) { System.getProperties().setProperty("sun.misc.ProxyGenerator.saveGeneratedFiles", "true"); return Proxy.newProxyInstance(object.getClass().getClassLoader(), object.getClass().getInterfaces(), new LogProxy(object)); } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println("good goods study"); Object invoke = method.invoke(o, args); System.out.println("day day up"); return invoke; } public static void main(String[] args) { Vegetable v = (Vegetable) LogProxy.getProxy(new Cabbage()); v.growUp(); } } }
- proxy源码解读
- 实际产生的对象是$Proxy0.class的对象,继承proxy,实现目标接口方法
- 执行目标接口时实际调用super也就是proxy的InvokationHandler的invoke对象
- 生成代理源码解读Proxy.newInstance(...)
- 跟进去会发现底层是利用asm动态生成二进制文件$Proxy0.class
Cglib
package club.interview.design_pattern.chapt6_proxy; import net.sf.cglib.proxy.Enhancer; import net.sf.cglib.proxy.MethodInterceptor; import net.sf.cglib.proxy.MethodProxy; import java.lang.reflect.Method; /** * @author QuCheng on 2020/6/15. */ public class CabbageCglib { public void growUp() { System.out.println("卷心菜慢慢长大"); } static class LogProxyCglib implements MethodInterceptor { @SuppressWarnings("unchecked") static <T> T getProxy(T o) { Enhancer enhancer = new Enhancer(); enhancer.setSuperclass(o.getClass()); enhancer.setCallback(new LogProxyCglib()); return (T) enhancer.create(); } @Override public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable { System.out.println("good good study"); // invokeSuper not invoke Object invoke = methodProxy.invokeSuper(o, objects); System.out.println("day day up"); return invoke; } } public static void main(String[] args) { CabbageCglib cabbageCglib = LogProxyCglib.getProxy(new CabbageCglib()); cabbageCglib.growUp(); } }
-
jdk
-
优点:jdk原生,可代理有接口实现的类
-
缺点:代理类必须实现接口
-
-
cglib
-
优点:
-
被代理类无需实现接口
-
实现简单,无需聚合
-
-
缺点:因为是采用继承,被代理类不能被final修饰
-