设计模式之JDK动态代理
1.代理模式
以租房为例子,你是一位出租用户,有的租客不会直接和你谈,而是去找中介谈。
租客(调用者)--->中介(代理对象)--->出租用户(真实对象,被代理)
2.什么是静态代理
由程序员创建或特定工具自动生成源代码,再对其编译。在程序运行前,代理类的.class文件就已经存在了。
代码:
被代理类
package com.bl.test3; public interface Person { void eat(); }
package com.bl.test3; public class Student implements Person { private String name; public Student(String name){ this.name=name; } @Override public void eat() { System.out.println(name+"在吃饭"); } }
代理类
package com.bl.test3; public class PersonProxy implements Person{ //被代理的学生 Student stu; public PersonProxy(Person p){ //只代理学生 if(p.getClass()==Student.class){ stu=(Student)p; } } public void eat(){ System.out.println("操作前"); stu.eat(); System.out.println("操作后"); } }
测试
package com.bl.test3; public class Test { public static void main(String[] args) { //被代理对象 Person p=new Student("小明"); //生成代理对象 Person person = new PersonProxy(p); person.eat(); } }
打印结果
操作前
小明在吃饭
操作后
3.什么是动态代理
在程序运行时,运用反射机制动态创建而成。
代码(JDK动态代理)
实现:一个是 InvocationHandler(Interface)、另一个则是 Proxy(Class)
被代理类
package com.bl.test2; public interface House { public void type(); public void shape(String shape); }
package com.bl.test2; public class Villa implements House { @Override public void shape(String shape) { System.out.println("我的形状是"+shape); } @Override public void type() { System.out.println("我的类型是别墅"); } }
代理类:
package com.bl.test2; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; //代理对象 public class HouseProxy implements InvocationHandler { //被代理对象
private Object house; public HouseProxy(Object stuObject){ this.house=stuObject; } //proxy:被代理对象 //method: 当前调用的方法 //args: 方法参数 @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println("--------操作前--------"); method.invoke(house, args); System.out.println("--------操作后--------"); return null; } }
测试类:
package com.bl.test2; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Proxy; public class Test { public static void main(String[] args) { House student=new Villa(); InvocationHandler handler=new HouseProxy(student); //Proxy.newProxyInstance(loader, interfaces, h) /* ClassLoader loader,:指定当前目标对象使用类加载器,获取加载器的方法是固定的 Class<?>[] interfaces,:目标对象实现的接口的类型,使用泛型方式确认类型 InvocationHandler h:事件处理,执行目标对象的方法时,会触发事件处理器的方法,会把当前执行目标对 */ //现在的House是一个代理对象,现在访问方法会进入到,代理的逻辑方法invoke里 House s=(House) Proxy.newProxyInstance(handler.getClass().getClassLoader(), student.getClass().getInterfaces(), handler); System.out.println(s.getClass().getName()); s.shape("很大"); s.type(); } }
打印结果:
$Proxy0 --------操作前-------- 我的形状是很大 --------操作后-------- --------操作前-------- 我的类型是别墅 --------操作后--------
应用:Spring AOP机制,RPC框架
作用:主要用来做方法的增强,让你可以在不修改源码的情况下,增强一些方法,在方法执行前后做任何你想做的事情(甚至根本不去执行这个方法)
如果有错误希望大家指出来,谢谢。