动态代理实现实例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 | import java.lang.reflect.InvocationHandler; import java.lang.reflect.Proxy; /* @author 12817 */ /** * 学生接口,能跑,能吃,能写作文。 */ interface Student { void eat(); void run(); void write(); } /** * 小韭菜,能跑,能吃,能写作文。 */ class OrdinaryStudents implements Student { @Override public void eat() { System.out.println( "我在吃饭!" ); } @Override public void run() { System.out.println( "我在跑步!" ); } @Override public void write() { System.out.println( "我在写作文!" ); } } public class DynamicProxy { public static void main(String[] args) { // 小韭菜学生类 Student ordinaryStudents = new OrdinaryStudents(); ordinaryStudents.eat(); ordinaryStudents.write(); // 现在有一位特殊的学生,他是区长的儿子,我们自然要对他额外照顾,要给他加一下功能。 // 一种思路是定义一个类:区长的儿子类,他继承自学生类,但世上儿子千千万,有区长的儿子,也有市长的儿子,更有省长的儿子,不能把他们挨个定义出来, // 现在就可以使用动态代理机制,动态的给区长的儿子加上功能,以后碰到市长、省长的儿子也同样处理。 // InvocationHandler作用就是,当代理对象的原本方法被调用的时候,会重定向到一个方法, // 这个方法就是InvocationHandler里面定义的内容,同时会替代原本方法的结果返回。 // InvocationHandler接收三个参数:proxy,代理后的实例对象。 method,对象被调用方法。args,调用时的参数。 InvocationHandler handler = (proxy, method, handlerArgs) -> { // 从定义eat方法。 if ( "eat" .equals(method.getName())) { System.out.println( "我可以吃香喝辣!" ); return null ; } // 从定义write方法。 if ( "write" .equals(method.getName())) { System.out.println( "我的作文题目是《我的区长父亲》。" ); // 调用普通学生类的write方法,流程还是要走的,还是要交一篇作文上去,不能太明目张胆。 method.invoke(ordinaryStudents, handlerArgs); System.out.println( "我的作文拿了区作文竞赛一等奖!so easy!" ); return null ; } return null ; }; // 对这个实例对象代理生成一个代理对象。 // 被代理后生成的对象,是通过People接口的字节码增强方式创建的类而构造出来的。它是一个临时构造的实现类的对象。 // loder和interfaces基本就是决定了这个类到底是个怎么样的类。而h是InvocationHandler,决定了这个代理类到底是多了什么功能. // 通过这些接口和类加载器,拿到这个代理类class。然后通过反射的技术复制拿到代理类的构造函数, // 最后通过这个构造函数new个一对象出来,同时用InvocationHandler绑定这个对象。 // 最终实现可以在运行的时候才切入改变类的方法,而不需要预先定义它。 Student sonOfDistrict = (Student) Proxy.newProxyInstance(ordinaryStudents.getClass().getClassLoader(), ordinaryStudents.getClass().getInterfaces(), handler); sonOfDistrict.eat(); sonOfDistrict.write(); } } |
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 全程不用写代码,我用AI程序员写了一个飞机大战
· DeepSeek 开源周回顾「GitHub 热点速览」
· 记一次.NET内存居高不下排查解决与启示
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· .NET10 - 预览版1新功能体验(一)