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 }
- 设置输入延时约束
- MySQL 死锁与日志二三事
- 一千个不用 Null 的理由
- TensorFlow强化学习入门(1.5)——上下文赌博机
- 以太坊·代币开发详解
- JSON Web Token - 在Web应用间安全地传递信息
- TensorFlow强化学习入门(2)——基于策略的Agents
- 用ABAP 生成二维码 QR Code
- CDS view注解解析 - @Environment.systemField
- Document flow API in SAP CRM and C4C
- Python基础知识4:文件操作
- Python基础知识6:格式化字符、颜色
- 给自定义控件(Web Control)添加事件的几种方法。前两种方法可以不实现IPostBackEventHandler
- 【开源】QuickPager ASP.NET2.0分页控件 v2.0.0.2版本。
- java教程
- Java快速入门
- Java 开发环境配置
- Java基本语法
- Java 对象和类
- Java 基本数据类型
- Java 变量类型
- Java 修饰符
- Java 运算符
- Java 循环结构
- Java 分支结构
- Java Number类
- Java Character类
- Java String类
- Java StringBuffer和StringBuilder类
- Java 数组
- Java 日期时间
- Java 正则表达式
- Java 方法
- Java 流(Stream)、文件(File)和IO
- Java 异常处理
- Java 继承
- Java 重写(Override)与重载(Overload)
- Java 多态
- Java 抽象类
- Java 封装
- Java 接口
- Java 包(package)
- Java 数据结构
- Java 集合框架
- Java 泛型
- Java 序列化
- Java 网络编程
- Java 发送邮件
- Java 多线程编程
- Java Applet基础
- Java 文档注释
- 不使用华为om工具如何手工部署openGauss主从流复制环境
- 比较两个等长的字符串,若相同,则输出Match!,若不同,则输出No Match!
- 逻辑回归算法原理及实现
- Python链表详细笔记
- 26个你需要学习的Firefox配置技巧,改进体验和加快浏览器响应速度
- Softmax算法原理及实现
- Android Activity 活动的生命周期
- Android学习笔记,不断更新
- cJSON,c语言的JSON库!
- 自己动手实现4大免费聊天机器人:小冰、图灵、腾讯、青云客
- Android Spinner下拉框的基本使用
- hadoop本地运行的两个案例。官方Grep案例、官方WordCount案例。
- 腾讯智能闲聊机器人详细开发教程
- 用PyTorch实现MNIST手写数字识别(非常详细)
- 手把手教你从零开始用Java写爬虫