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 条评论
登录 后参与评论

相关文章

来自专栏LinkedBear的个人空间

唠唠SE的面向对象-04——this关键字 原

this关键字代表是对象的引用。也就是this在指向一个对象,所指向的对象就是调用该方法的对象引用。

442
来自专栏Kevin-ZhangCG

[ Java学习基础 ] Java构造函数

1946
来自专栏Java编程

Java动态代理机制详解

在学习Spring的时候,我们知道Spring主要有两大思想,一个是IoC,另一个就是AOP,对于IoC,依赖注入就不用多说了,而对于Spring的核心AOP来...

4071
来自专栏好好学java的技术栈

Java提升篇:对象克隆(复制)

1123
来自专栏null的专栏

设计模式——类图以及类与类之间的关系

    设计模式在程序设计上有着很重要的作用,使用设计模式可以使得代码更容易被理解,使得代码更规范,真正实现工程化。 一、用UML表示一个类 ? 类图一般是三行...

3304
来自专栏技术之路

c++多重继承小结

如果一个类从两个不同的类里继承两个同名的成员,则需要在派生类中使用类限定符来区分他们。 即在从A和B派生出来的c类中使用a::Show()和B::Show()来...

1717
来自专栏微信公众号:Java团长

Java提高篇——对象克隆(复制)

不仅仅是int类型,其它七种原始数据类型(boolean,char,byte,short,float,double.long)同样适用于该类情况。

1083
来自专栏Java帮帮-微信公众号-技术文章全总结

第十三天 面向对象-final static 匿名对象内部类包代码块【悟空教程】

1244
来自专栏JackieZheng

Spring读书笔记——bean创建(下)

有关Spring加载bean系列,今天这是最后一篇了,主要接上篇对于从Spring容器中获取Bean的一些细节实现的补充。 《Spring读书笔记——bean加...

1787
来自专栏Java学习之路

04 Spring框架 依赖注入(一)

整理了一下之前学习spring框架时候的一点笔记。如有错误欢迎指正,不喜勿喷。 上一节我们讲了几个bean的一些属性,用来限制我们实例创建过后的状态。 但是...

3255

扫码关注云+社区