博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Java动态代理
阅读量:5906 次
发布时间:2019-06-19

本文共 3009 字,大约阅读时间需要 10 分钟。

hot3.png

代理模式:

代理模式的主要作用有两点:

1. 因为某些原因一个客户不想或者不能直接引用另一个对象,而代理对象可以在客户端和目标对象之间起到中介的作用。

    Q: 何为“不想或者不能直接引用另一个对象”?

    A: 如果执行某个操作需要进行远程调用网络另一端的计算机,如果不使用代理模式,则需要将复杂的网络通信部分硬编码入客户端。为了简化客户端的行为,可以使用代理模式,由客户端通过代理对象向远程的计算机发出指令,网络通信部分则有代理对象完成。

2. 在代理对象调用被代理对象的方法前后,可以附加一些额外的操作(如对数据加密)。

代理模式一般涉及到的角色:

1. 抽象角色

    抽象角色implements by代理类和被代理类,即为后两者的公共接口。

2. 代理角色

    代理角色含有对真实角色的引用,从而可以操作真实对象,除此之外代理角色可以在执行真实角色操作时,附加其额外相当于对真实角色进行封装。 

3.    真实角色

        真实角色也就是被代理的角色,是客户最终向要调用的角色。

由于代理角色和真实角色同时实现了公共的接口,因此在客户看来,对代理角色的操作与对真实的角色的操作并无差别。

动态代理:

1. 通俗的说法:在编译阶段代理对象并不知道自己要去调用哪个被代理对象的方法。

2. 动态代理是程序在运行时动态的加载代理对象(根据所要代理对象的不同动态加载),动态的调用被代理类的方法。

Java动态代理的主要过程(同时参见以下代码):

  核心方法:Proxy类的静态方法newProxyInstance(ClassLoader loader,Class<?>[] interfaces, InvocationHandler h)

    InvocationHandler接口,子类需重写invoke(Object proxy, Method method, Object[] args)方法

        proxy:the proxy instance that the method was invoked on. 一般是指代理类

        method:被代理的方法(通过java反射获得),args方法的参数。

    loader 类装载器,与JVM类父委托加载机制有关。

    interfaces 是真实类所拥有的全部接口的数组。

1 /*
2  * Base.java
3  * 抽象角色类:被代理对象与代理对象的公共接口
4  */
5 public interface Base {
6      
7     abstract public void doMethod();
8  
9 }
01 /*
02  * Target1.java
03  * 目标角色:被代理的对象
04  */
05 public class Target1 implements Base {
06      
07     @Override
08     public void doMethod() {
09         System.out.println("Target1 Method has been invoked");
10     }
11 }
01 /*
02  * Target2.java
03  * 目标角色:被代理的对象
04  */
05 public class Target2 implements Base {
06  
07     @Override
08     public void doMethod() {
09         System.out.println("Target2 Method has been invoked");
10     }
11 }
01 /*
02  * MyHandler.java
03  * 该代理类的内部属性为Object类,实际使用时通过该类的构造函数MyHandler(Object obj)对其赋值;
04  * 此外,在该类还实现了invoke方法,该方法中的 method.invoke(sub,args);
05  * 其实就是调用被代理对象的将要被执行的方法,方法参数sub是实际的被代理对象,
06  * args为执行被代理对象相应操作所需的参数。
07  * 通过动态代理类,我们可以在调用之前或之后执行一些相关操作
08  */
09 import java.lang.reflect.InvocationHandler;
10 import java.lang.reflect.Method;
11  
12 public class MyHandler implements InvocationHandler {
13     Object obj;
14  
15     public MyHandler() {
16     }
17  
18     public MyHandler(Object obj) {
19         this.obj = obj;
20     }
21  
22     @Override
23     public Object invoke(Object proxy, Method method, Object[] args)
24             throws Throwable {
25         System.out.println("before doMethod");
26         method.invoke(obj, args);
27         System.out.println("after doMethod");
28         return null;
29     }
30 }
01 /*
02  * Client.java
03  * 客户类:客户在此与代理对象发生直接通信
04  */
05 import java.lang.reflect.InvocationHandler;
06 import java.lang.reflect.Proxy;
07  
08 public class Client {
09     public static void main(String[] args) {
10         Target1 target1 = new Target1();    // 显示指定被代理类Target1
11         InvocationHandler h1 = new MyHandler(target1);
12         Class<?> cls1 = target1.getClass();
13         Base base1 = (Base) Proxy.newProxyInstance(cls1.getClassLoader(),
14                 cls1.getInterfaces(), h1);
15         base1.doMethod();
16          
17         Target2 target2 = new Target2();    // 显示指定被代理类Target2
18         InvocationHandler h2 = new MyHandler(target2);
19         Class<?> cls2 = target2.getClass();
20         Base base2 = (Base) Proxy.newProxyInstance(cls2.getClassLoader(),
21                 cls2.getInterfaces(), h2);
22         base2.doMethod();
23     }
24 }

转载于:https://my.oschina.net/lvzjane/blog/97945

你可能感兴趣的文章
extmail集群的邮件负载均衡方案 [lvs dns postfix]
查看>>
更改UIView的背景
查看>>
APUE第15章学习扎记之程序的存储区布局试验
查看>>
ubuntu升级16.04 inter idea 中文输入法无效
查看>>
三目运算判断jsp脚本里面的值
查看>>
sshtunnel在本地访问云服务器mysql
查看>>
小蚂蚁学习APP接口开发(1)—— json方式封装通信接口
查看>>
我的友情链接
查看>>
CDN相关
查看>>
Tomcat的设置4——Tomcat的体系结构与设置基于端口号的虚拟主机
查看>>
我的友情链接
查看>>
ftp协议基础
查看>>
访问共享经常中断
查看>>
人生的交易
查看>>
MySql
查看>>
sql server 下载安装标记
查看>>
js运算符(运算符的结合性)
查看>>
idea 编译级别的设置
查看>>
内置对象Array的原型对象中添加方法
查看>>
6大设计原则
查看>>