JDK动态代理模式
来源:互联网 发布:淘宝上聚划算的要求 编辑:程序博客网 时间:2024/05/22 09:44
动态代理模式是对方法的横向增强,它不同于继承,继承通过对父类方法的覆盖,重新对方法进行定义,而横向增强是对方法执行前和执行后的一个增加,不重新定义方法。
代理方式有两种:
jdk代理模式:对接口或实现接口的类进行代理
CGLib代理模式:对类进行代理
jdk动态代理机制中必不可少的类和接口,一个是InvocationHandler(接口)、另一个是Proxy(类)。
必须有一个类实现InvocationHandler接口,从而实现其中的invoke()方法,在invoke()方法中对代理的方法进行增强。我们来看看API文档中对这个类是怎么描述的:
InvocationHandler is the interface implemented by the invocation handler of a proxy instance. Each proxy instance has an associated invocation handler. When a method is invoked on a proxy instance, the method invocation is encoded and dispatched to the invoke method of its invocation handler.
每一个动态代理类都必须要实现InvocationHandler这个接口,并且每个代理类的实例都关联到了一个handler,当我们通过代理对象调用一个方法的时候,这个方法的调用就会被转发为由InvocationHandler这个接口的 invoke 方法来进行调用。我们来看看InvocationHandler这个接口的唯一一个方法 invoke 方法:
Object invoke(Object proxy, Method method, Object[] args) throws Throwableproxy: 指代我们所代理的那个真实对象method: 指代的是我们所要调用真实对象的某个方法的Method对象args: 指代的是调用真实对象某个方法时接受的参数
我们来看看Proxy类的描述:
Proxy provides static methods for creating dynamic proxy classes and instances, and it is also the superclass of all dynamic proxy classes created by those methods.
Proxy这个类的作用就是用来动态创建一个代理对象的类,它提供了许多的方法,但是我们用的最多的就是 newProxyInstance 这个方法:
public static Object newProxyInstance(ClassLoader loader,Class<?>[] interfaces, InvocationHandler h) throws IllegalArgumentExceptionloader:一个ClassLoader对象,定义了由哪个ClassLoader对象来对生成的代理对象进行加载,可以是实现类的ClassLoader也可以是接口的ClassLoaderinterfaces:一个Interface对象的数组,表示的是我将要给我需要代理的对象提供一组什么接口,如果我提供了一组接口给它,那么这个代理对象就宣称实现了该接口(多态),这样我就能调用这组接口中的方法了h:一个InvocationHandler对象,表示的是当我这个动态代理对象在调用方法的时候,会关联到哪一个InvocationHandler对象上
这个方法的作用就是得到一个动态代理的对象,通过这个对象可以调用类中被增强后的方法,实际就是调用h中的invoke()方法。
示例代码:
//接口package com.zhangyike.proxy;public interface Person { public void speak(); public void eat();}
//接口的实现类,可有可无package com.zhangyike.proxy;public class ImpPerson implements Person { @Override public void speak() { System.out.println("实现类中说话"); } @Override public void eat() { System.out.println("实现类中吃"); }}
//InvocationHander的实现类package com.zhangyike.proxy;import java.lang.reflect.InvocationHandler;import java.lang.reflect.Method;import java.lang.reflect.Proxy;public class Hander implements InvocationHandler { Object t; Hander(Object t){ this.t = t; } Hander(){ } public Object creatImplementsClass(){ //对接口的实现类对方法进行增强,参数将接口、接口的实现类与InvocationHandler对象关联,也就是说调用代理类中的方法就是调用InvocationHandler实现类中的invoke() Object instance = Proxy.newProxyInstance(t.getClass().getClassLoader(), t.getClass().getInterfaces(), this); return instance; } public Object creatInterfaceClass(Class<?> ifClass){ //只有接口没有接口实现类去得到代理对象。将接口与InvocationHandler对象关联,也就是说调用代理类中的方法就是调用InvocationHandler实现类中的invoke() Object instance = Proxy.newProxyInstance(ifClass.getClassLoader(), new Class[]{ifClass}, this); return instance; } //调用该方法 @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { String name = method.getName(); if (name.equals("speak")) {//对说方法增强 System.out.println("人在说话前"); //t!=null表示有实现接口的类,只提供接口不能调用该方法 if (t != null) { method.invoke(t, args); } System.out.println("人在说话后"); }else{//对吃方法增强 if (t != null) { method.invoke(t, args); } System.out.println(name); } return null; }}
Demo测试类:package com.zhangyike.proxy;public class DemoTest { public static void main(String[] args) { test1(); test(); } public static void test(){ Hander hander = new Hander(); //获取没有接口实现类的对象 Person person = (Person)hander.creatInterfaceClass(Person.class); System.out.println("对接口增强:"); person.speak(); System.out.println("------------------------------------------------------"); person.eat(); } public static void test1(){ ImpPerson impPerson = new ImpPerson(); Hander hander = new Hander(impPerson); //获取没有接口实现类的对象 Person person = (Person) hander.creatImplementsClass(); System.out.println("对实现类增强:"); person.speak(); System.out.println("*******************************************************"); person.eat(); }}
注意事项:
在测试类的test1()方法中,获取代理类后,将代理对象转换,只能转换为接口类,不能转换为接口的实现类,否则会出现异常:
Exception in thread “main” java.lang.ClassCastException: com.sun.proxy.$Proxy0 cannot be cast to com.zhangyike.proxy.ImpPerson
at com.zhangyike.proxy.DemoTest.test1(DemoTest.java:23)
at com.zhangyike.proxy.DemoTest.main(DemoTest.java:5)
这个也很好理解:JDK动态代理必须要有接口,对接口中的方法进行增强,而实现类中有他特有的方法,代理类无法对他进行增强,通过Proxy对象只能得到接口对象,不能得到实现类对象。
- JDK动态代理模式
- JDK动态代理模式
- JDK动态代理模式
- JDK动态代理模式
- 代理模式,JDK动态代理
- 代理模式-JDK动态代理
- 动态代理模式之JDk动态代理
- 代理模式,JDK动态代理,SpringAOP来龙去脉
- 代理模式和JDK动态代理
- 代理模式之JDK动态代理
- java代理模式、动态代理(JDK,CGLIB)
- 代理模式二(JDK动态代理)
- java 代理模式 jdk动态代理
- 代理模式之jdk动态代理
- 代理模式之jdk动态代理
- 代理模式(静态代理、jdk动态代理)
- 设计模式---动态代理(基于JDK的动态代理)
- java动态代理模式Proxy之JDK动态代理机制
- 常用JVM配置参数
- android studio中导入三方sdk的so文件
- C++11 新标准(四)
- Hadoop2.7.3配置记录
- codeforces796E Exam Cheating
- JDK动态代理模式
- HDU 3071-Gcd & Lcm game-线段树+素因子分解-[解题报告]HOJ
- 如何将文件加入路径,并成功使用roscd和rosed
- iOS 安全模型浅析(五) ---- 挑战AppStore审核
- Java数组(Array)_基本概念_内存分析
- 【数据库】- mysql使用集锦
- 【最全,最有效】WIN7下的并行环境搭建
- 【BFS瞎搜】skiing
- C语言中栈的建立和应用