JAVA动态代理学习
2016-09-30 11:25
253 查看
代理模式分为静态代理和动态代理,静态代理中的代理是由程序员自己编写的,也就是说在我们的代码运行前,代理类的class编译文件就已存在;而动态代理与其相反,代理类是在运行阶段由JVM帮忙生成。java也给我们提供了一个便捷的动态代理接口
InvocationHandler,实现该接口需要重写其invoke方法,如下:
可以看到,我们声明一个Object的引用,该引用将指向被代理类,而我们调用被代理类的接口方法时,则会在invoke方法中执行。也就是说我们原来由代理类所做的工作现在由InvocationHandler来处理,不再需要关心到底代理谁,客户代码:
其他代码:
运行结果:
可以看到调用subject.getClass().getName()打印为Proxy0类型,接着调用hello方法就会进入DynamicProxy中的invoke方法中。
如果我们要换个接口,可以继续用这个动态代理,如下:
打印结果:
由此可见动态代理通过一个代理类来代替N多个被代理类,其实质是对代理者与被代理者进行解耦,使得两者没有直接的耦合关系,相对静态代理则只能为给定接口下的实现类做代理,如果接口不同那么就需要重新定义不同的代理类,但是静态代理更符合面向对象。
InvocationHandler,实现该接口需要重写其invoke方法,如下:
public class DynamicProxy implements InvocationHandler { // 这个就是我们要代理的真实对象 private Object subject; // 构造方法,给我们要代理的真实对象赋初值 public DynamicProxy(Object subject) { this.subject = subject; } @Override public Object invoke(Object arg0, Method method, Object[] args) throws Throwable { // 在代理真实对象前我们可以添加一些自己的操作 System.out.println("before rent house"); System.out.println("Method:" + method); // 当代理对象调用真实对象的方法时,其会自动的跳转到代理对象关联的handler对象的invoke方法来进行调用 method.invoke(subject, args); // 在代理真实对象后我们也可以添加一些自己的操作 System.out.println("after rent house"); return null; } }
可以看到,我们声明一个Object的引用,该引用将指向被代理类,而我们调用被代理类的接口方法时,则会在invoke方法中执行。也就是说我们原来由代理类所做的工作现在由InvocationHandler来处理,不再需要关心到底代理谁,客户代码:
public class Client { public static void main(String[] args) { // 我们要代理的真实对象 Subject realSubject = new RealSubject(); // 我们要代理哪个真实对象,就将该对象传进去,最后是通过该真实对象来调用其方法的 InvocationHandler handler = new DynamicProxy(realSubject); /* * 通过Proxy的newProxyInstance方法来创建我们的代理对象,我们来看看其三个参数 第一个参数 * handler.getClass().getClassLoader() * ,我们这里使用handler这个类的ClassLoader对象来加载我们的代理对象 * 第二个参数realSubject.getClass(). * getInterfaces(),我们这里为代理对象提供的接口是真实对象所实行的接口, * 表示我要代理的是该真实对象,这样我就能调用这组接口中的方法了 第三个参数handler, 我们这里将这个代理对象关联到了上方的 * InvocationHandler 这个对象上 */ Subject subject = (Subject) Proxy.newProxyInstance(handler.getClass() .getClassLoader(), realSubject.getClass().getInterfaces(), handler); System.out.println(subject.getClass().getName()); subject.hello("world"); } }
其他代码:
public interface Subject { public void rent(); public void hello(String str); }
public class RealSubject implements Subject { @Override public void rent() { System.out.println("I want to rent my house"); } @Override public void hello(String str) { System.out.println("hello: " + str); } }
运行结果:
com.sun.proxy.$Proxy0 before rent house Method:public abstract void com.zte.dynamicproxy.Subject.hello(java.lang.String) hello: world after rent house
可以看到调用subject.getClass().getName()打印为Proxy0类型,接着调用hello方法就会进入DynamicProxy中的invoke方法中。
如果我们要换个接口,可以继续用这个动态代理,如下:
public interface Subject1 { public void rent(); }
public class RealSubject1 implements Subject1 { @Override public void rent() { System.out.println("1 I want to rent my house"); } }
public class Client { public static void main(String[] args) { Subject1 realSubject1 = new RealSubject1(); InvocationHandler handler = new DynamicProxy(realSubject1); Subject1 subject = (Subject1) Proxy.newProxyInstance(handler.getClass() .getClassLoader(), realSubject1.getClass().getInterfaces(), handler); System.out.println(subject.getClass().getName()); subject.rent(); } }
打印结果:
com.sun.proxy.$Proxy0 before rent house Method:public abstract void com.zte.dynamicproxy.Subject1.rent() 1 I want to rent my house after rent house
由此可见动态代理通过一个代理类来代替N多个被代理类,其实质是对代理者与被代理者进行解耦,使得两者没有直接的耦合关系,相对静态代理则只能为给定接口下的实现类做代理,如果接口不同那么就需要重新定义不同的代理类,但是静态代理更符合面向对象。
相关文章推荐
- java 动态代理学习(Proxy,InvocationHandler)
- java 之 动态代理学习示例
- java反射--动态代理学习案例代码
- java学习笔记---类型信息(type information)、反射机制与动态代理
- java动态代理的学习
- java动态代理的学习
- Java动态代理学习2——静态代理和动态代理并对照spring的通知
- java动态代理学习笔记
- Java动态代理学习1——静态代理
- 反射和动态代理之Java学习总结
- Java动态代理学习文章(二)
- java动态代理学习笔记
- java动态代理学习笔记
- 学习Spring必学的Java基础知识(2)----动态代理
- java动态代理学习(一)
- java 动态代理学习
- 学习Spring必学的Java基础知识(2)----动态代理
- java动态代理学习
- java动态代理学习笔记
- 学习:java设计模式—动态代理模式