动态代理
发布时间:2020-12-15 07:59:42 所属栏目:Java 来源:网络整理
导读:动态代理: ??? 原理:使用一个代理将对象包装起来,然后用该对象取代原始对象,任何对原始对象的调用都要通过代理,代理对象决定是否以及何时讲方法调用转到原始对象上 动态代理: ?? 1. 基于接口?? -----JDK动态代理 ?? 2.基于继承??? -----CGlib动态代理
动态代理: ??? 原理:使用一个代理将对象包装起来,然后用该对象取代原始对象,任何对原始对象的调用都要通过代理,代理对象决定是否以及何时讲方法调用转到原始对象上 动态代理: ?? 1. 基于接口?? -----JDK动态代理 ?? 2.基于继承??? -----CGlib动态代理 ? ? ?? 类似微商,微商就是代理,他宣传买东西,你通过他买东西,但是真正买东西的还是卖家: ?? 比如程序代码计算器,如果想增减日志代理、验证代理等,但是计算实现功能依然是【程序代码计算器】 //接口,目标类和代理类都实现同一个接口 ? public class ArithmeticCalculatorImpl implements ArithmeticCalculator { @Override public int add(int a,int b) { int result = a + b; return result; } @Override public int sub(int a,int b) { int result = a - b; return result; } @Override public int mul(int a,int b) { int result = a * b; return result; } @Override public int div(int a,int b) { int result = a / b; return result; } } ? ? import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; /** * JDK的动态代理 * 1. Proxy:是所有动态类的父类,专门为用户生成代理类或者代理对象 * @CallerSensitive * public static Class<?> getProxyClass(ClassLoader loader,* Class<?>... interfaces) * 用于生成代理类的Class对象 * @CallerSensitive * public static Object newProxyInstance(ClassLoader loader,* Class<?>[] interfaces,* InvocationHandler h) * 用于生成代理类对象 * 2. InvocationHandler:完成动态代理的整个过程。 * public Object invoke(Object proxy,Method method,Object[] args) * throws Throwable; * */ public class ArithmeticCalculatorProxy { private Object target; public ArithmeticCalculatorProxy(Object target) { this.target = target; } public Object getProxy(){ Object proxy; /** * loader: ClassLoader对象,类加载器对象,帮我们加载动态生成的代理类 * interfaces:接口们,提供目标对象的所有接口,目的是让代理对象与目标对象都有接口中相同的方法 * InvocationHandler : 接口 */ ClassLoader classLoader = target.getClass().getClassLoader(); Class<?>[] interfaces = target.getClass().getInterfaces(); proxy = Proxy.newProxyInstance(classLoader,interfaces,new InvocationHandler() { /** * invoke: 代理对象调用代理方法,会回来调用invoke方法 * proxy:代理对象,在invoke方法中一般不会使用 * method:正在被调用的方法对象 * args: 正在被调用方法的参数 */ @Override public Object invoke(Object proxy,Object[] args) throws Throwable { //讲方法的调用转到目标对象上 //获取方法的名字 String methodName = method.getName(); //记录日志 System.out.println(" zhe method "+methodName+" begin"); Object result = method.invoke(target,args); System.out.println(" zhe method "+methodName+" end"); return result; } }); return proxy; } } ? ? ?模拟动态代理底层实现 class $Proxy0 extends Proxy implements ArithmeticCalculator{ protected $Proxy0(InvocationHandler h) { super(h); } @Override public int add(int a,int b) { //return super.h.invoke(this,方法对象,方法参数); return 0; } @Override public int sub(int a,int b) { return 0; } @Override public int mul(int a,int b) { return 0; } @Override public int div(int a,int b) { return 0; } } ? ? ? public class Demo { public static void main(String[] args)throws Exception { ArithmeticCalculatorImpl arithmeticCalculator = new ArithmeticCalculatorImpl(); Object proxy = new ArithmeticCalculatorProxy(arithmeticCalculator).getProxy(); /** * 第一步 : 生成代理类, * (1) proxy = Proxy.newProxyInstance(classLoader,new InvocationHandler().... * 通过这个方法生成代理对象, * * 第二步: 根据代理类生成代理对象 * Object proxy = new ArithmeticCalculatorProxy(arithmeticCalculator).getProxy(); * * 第三步:对象调用相应方法 proxy3.add(1,1) * 第三步底层模拟如下 * class $Proxy0 extends Proxy implements ArithmeticCalculator{ * * protected $Proxy0(InvocationHandler h) { * super(h); * } * * @Override * public int add(int a,int b) { * 此处会调用此方法 super.h.invoke(this,方法对象,方法参数);它会调用 Invocation接口中的invoke方法 * public Object invoke(Object proxy,Object[] args) * throws Throwable; * //return super.h.invoke(this,方法对象,方法参数); * return 0; * } * * @Override * public int sub(int a,int b) { * return 0; * } * * @Override * public int mul(int a,int b) { * return 0; * } * * @Override * public int div(int a,int b) { * return 0; * } * } */ ArithmeticCalculator proxy3 =(ArithmeticCalculator)proxy; System.out.println(proxy3.add(1,1)); } } (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |
相关内容
- LinkedHashSet迭代时的java.util.ConcurrentModificationEx
- NIO Java NIO 通讯的简单示例
- Java为参数分配一个新值,这被认为是不好的做法吗?
- 在任务栏图标上使用java点击左键打开弹出窗口(菜单)
- JSP Request.isRequestedSessionIdFromURL()方法:判断sess
- java – 使用Jersey客户端在POST中发送名称值对
- java – 通过Composition(接口和类)进行类型转换
- 浅谈Java工程读取resources中资源文件路径的问题
- Month和java.util.Formatter
- java – 如何检测mime类型是否为可执行文件?