java反射实现动态代理

参考:http://www.cnblogs.com/rollenholt/archive/2011/09/02/2163758.html

http://my.oschina.net/lyp3314/blog/136589

反射可以通过class来创建对象或者修改对象。这样就提供了一个操作对象的方法。

下面拷贝前辈的总结:

<反射机制>

    为了更好的理解java的反射机制,最好先对java的泛型有所了解。java泛型就是参数化类型,即为所操作的数据类型指定一个参数。如果只指定了<?>,而没有extends,则默认是允许Object及其下的任何Java类。也就是任意类

1. Java运行时,对任意一个类,想知道它有哪些属性和方法,对于任意一个对象,想调用它的任意一个方法,都是可以实现的,这来自JAVA的反射机制  2. JAVA的反射机制主要功能:      (1)在运行时判断任意一个对象所属的类。      (2)在运行时构造任意一个类的对象。      (3)在运行时判断任意一个类所具有的成员变量和方法。      (4)在运行时调用任意一个对象的方法      前提是在运行时,不是编译时,也就是在运行前并不知道调用哪一个类,通过反射就可以做到这些  3.在JDK中,主要由以下类来实现JAVA反射机制,这些类位于java.lang.reflect包中:      Class类:代表一个类      Field 类:代表类的成员变量(成员变量也称为类的属性)。      Method类:代表类的方法。      Constructor 类:代表类的构造方法。      Array类:提供了动态创建数组,以及访问数组的元素的静态方法  4. Class类是Reflection API 中的核心类,它有以下方法      getName():获得类的完整名字      getFields():获得类的public类型的属性      getDeclaredFields():获得类的所有属性      getMethods():获得类的public类型的方法      getDeclaredMethods():获得类的所有方法      getMethod(String name, Class[] parameterTypes):获得类的特定方法,name参数指定方法的名字,parameterTypes 参数指定方法的参数类型      getConstructors():获得类的public类型的构造方法      getConstructor(Class[] parameterTypes):获得类的特定构造方法,parameterTypes 参数指定构造方法的参数类型      newInstance():通过类的不带参数的构造方法创建这个类的一个对象 

<代理模式>

1. 代理模式的作用是:为其他对象提供一种代理以控制对这个对象的访问。在某些情况下,一个客户不想或者不能直接引用另一个对象,而代理对象可以在客户端和目标对象之间起到中介的作用

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

(1)抽象角色:声明真实对象和代理对象的共同接口

(2)代理角色:代理对象角色内部含有对真实对象的引用,从而可以操作真实对象,同时代理对象提供与真实对象相同的接口以便在任何时刻都能代替真实对象。同时,代理对象可以在执行真实对象操作时,附加其他的操作,相当于对真实对象进行封装

(3)真实角色:代理角色所代表的真实对象,是我们最终要引用的对象

【实例】

Subject  抽象类  抽象角色 定义一个抽象方法request

RealSubject  真实角色  继承了抽象类Subject 实现抽象方法request

ProxySubject  代理角色  同样继承抽象类Subject实现抽象方法request

 1 package com.test.reflect;
 2 
 3 /**
 4  * Created by mrf on 2015/11/26.
 5  * 测试动态代理
 6  * Subject  抽象类  抽象角色 定义一个抽象方法request
 7     RealSubject  真实角色  继承了抽象类Subject 实现抽象方法request
 8      ProxySubject  代理角色  同样继承抽象类Subject实现抽象方法request
 9  */
10 public class DynamicProxy2 {
11 
12     //客户端调用
13     public static void main(String[] args) {
14         Subject2 sub = new ProxySubject();
15         sub.request();
16     }
17 
18 }
19 //抽象角色
20 abstract class  Subject2{
21     abstract public void request();
22 }
23 
24 //真实角色
25  class RealSubject2 extends Subject2{
26     public RealSubject2(){}
27     @Override
28     public void request() {
29         System.out.println("局长办事了!");
30     }
31 }
32 
33 //代理角色
34 class ProxySubject extends Subject2{
35 private RealSubject2 realSubject2;//以真实角色 做为代理的属性
36     public ProxySubject(){}
37     //该方法封装了真实对象的request方法
38     public void request() {
39         preRequest();
40         if(realSubject2==null){
41             realSubject2=new RealSubject2();
42         }
43         realSubject2.request();//此处执行真实对象的request方法
44         postRequest();
45     }
46 
47     private void postRequest() {
48         System.out.println("秘书回来了!");
49     }
50 
51     private void preRequest() {
52         System.out.println("秘书找局长");
53     }
54 }

在客户端里,并没有直接去调用真实对象中的request方法,但是却实现了真实对象中的方法,是通过代理对象间接调用的,这里体现了代理模式的特点

1. 如果要按照上述的方法使用代理模式,那么真实角色必须是事先已经存在的,并将其作为代理对象的内部属性。但是实际使用时,一个真实角色必须对应一个 代理角色,如果大量使用会导致类的急剧膨胀;此外,如果事先并不知道真实角色,该如何使用代理呢?这个问题可以通过Java的动态代理类来解决

2. 动态代理是指客户通过代理类来调用其它对象的方法

3. Java动态代理类位于java.lang.reflect包下,一般主要涉及到以下两个类: 

(1)Interface InvocationHandler:该接口中仅定义了一个方法 public object invoke(Object obj,Method method, Object[] args) 在实际使用时,第一个参数obj一般是指代理类,method是被代理的方法,如上例中的request(),args为该方法的参数数组。 这个抽象方法在代理类中动态实现。 

(2)Proxy:该类即为动态代理类,作用类似于上例中的ProxySubject

1. 动态代理的步骤

(1).创建一个实现接口InvocationHandler的类,它必须实现invoke方法

(2).创建被代理的类以及接口

(3).通过Proxy的静态方法

newProxyInstance(ClassLoader loader, Class[] interfaces, InvocationHandler h) 创建一个代理

(4).通过代理调用方法

<动态代理>

实现:

 1 package com.test.reflect;
 2 
 3 import java.lang.reflect.InvocationHandler;
 4 import java.lang.reflect.Method;
 5 import java.lang.reflect.Proxy;
 6 
 7 /**
 8  * Created by Administrator on 2015/11/24.
 9  * 测试动态代理
10  */
11 public class DynamicProxy {
12     public static void main(String[] args) {
13         MyInvocationHandler demo = new MyInvocationHandler();
14         Subject sub= (Subject)demo.bind(new RealSubject());
15         String info = sub.say("Rollen", 20);
16         System.out.println(info);
17     }
18 
19 }
20 
21 //定义接口
22 interface Subject{
23     public String say(String name,int age);
24 }
25 
26 //定义真实项目
27 class RealSubject implements Subject{
28     public RealSubject(){}
29     @Override
30     public String say(String name, int age) {
31         System.out.println(name+"开始工作");
32         return name+" "+age;
33     }
34 }
35 
36 class MyInvocationHandler implements InvocationHandler{
37     private Object obj;
38     public MyInvocationHandler(){}
39     public MyInvocationHandler(Subject obj){
40         this.obj = obj;
41     }
42 
43     public Object bind(Object obj){
44         this.obj = obj;
45         return Proxy.newProxyInstance(obj.getClass().getClassLoader(),obj.getClass().getInterfaces(),this);
46     }
47 
48     @Override
49     public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
50         System.out.println("预处理工作");
51         Object temp = method.invoke(this.obj,args);
52         System.out.println("后续工作");
53         return temp;
54     }
55 
56 
57 }

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏飞雪无情的博客

Go语言 | Go 1.9 新特性 Type Alias详解

北京时间2017.08.25,Go1.9正式版发布了。Go1.9经历了2个beta,好几个月,终于定了,发布了正式版本。Go 1.9包含了很多改变,比如类型别名...

734
来自专栏mySoul

jQuery(一)

jquery为一种库,属于最基础的一个库,伴随着h5的到来,很多jquery的规则直接融入到了规则本身了,直接使用原生的js也能达到相同的目的。虽然如此,不过依...

1024
来自专栏学习力

《Java从入门到放弃》框架入门篇:Struts2的常用验证方式(二)

1529
来自专栏待你如初见

Day01

不推荐使用强制的类型转换,它容易丢失数据,除非不得已,并且你确定不会出现数据丢失才可以使用。

1325
来自专栏haifeiWu与他朋友们的专栏

Java命令之javap初探

javap是jdk自带的一个工具在jdk安装目录的/bin下面可以找到,可以对代码反编译,也可以查看java编译器生成的字节码,对代码的执行过程进行分析,了解j...

512
来自专栏我爱编程

Day14IO编程

读文件 Python引入了with语句来自动帮我们调用close()方法: with open('/path/to/file', 'r') as f: ...

3035
来自专栏海天一树

小朋友学C语言(34):main函数的参数

C/C++中的main()函数,可以带形式参数,也可以不带形式参数。这两种形式分别为: 1)int main() 2)int main(int argc, ch...

2576
来自专栏JetpropelledSnake

Django学习笔记之Django模版系统

1012
来自专栏java达人

jsp中的JSTL与EL表达式用法及区别(一)

对于JSTL和EL之间的关系,这个问题对于初学JSP的朋友来说,估计是个问题,下面来详细介绍一下JSTL和EL表达式他们之间的关系,以及JSTL和EL一些相关概...

1805
来自专栏Python爱好者

Java基础笔记19

1286

扫描关注云+社区