java反射实现动态代理

时间:2023-12-16 21:55:50

参考: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

 package com.test.reflect;

 /**
* Created by mrf on 2015/11/26.
* 测试动态代理
* Subject 抽象类 抽象角色 定义一个抽象方法request
RealSubject 真实角色 继承了抽象类Subject 实现抽象方法request
ProxySubject 代理角色 同样继承抽象类Subject实现抽象方法request
*/
public class DynamicProxy2 { //客户端调用
public static void main(String[] args) {
Subject2 sub = new ProxySubject();
sub.request();
} }
//抽象角色
abstract class Subject2{
abstract public void request();
} //真实角色
class RealSubject2 extends Subject2{
public RealSubject2(){}
@Override
public void request() {
System.out.println("局长办事了!");
}
} //代理角色
class ProxySubject extends Subject2{
private RealSubject2 realSubject2;//以真实角色 做为代理的属性
public ProxySubject(){}
//该方法封装了真实对象的request方法
public void request() {
preRequest();
if(realSubject2==null){
realSubject2=new RealSubject2();
}
realSubject2.request();//此处执行真实对象的request方法
postRequest();
} private void postRequest() {
System.out.println("秘书回来了!");
} private void preRequest() {
System.out.println("秘书找局长");
}
}

在客户端里,并没有直接去调用真实对象中的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).通过代理调用方法

<动态代理>

实现:

 package com.test.reflect;

 import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy; /**
* Created by Administrator on 2015/11/24.
* 测试动态代理
*/
public class DynamicProxy {
public static void main(String[] args) {
MyInvocationHandler demo = new MyInvocationHandler();
Subject sub= (Subject)demo.bind(new RealSubject());
String info = sub.say("Rollen", 20);
System.out.println(info);
} } //定义接口
interface Subject{
public String say(String name,int age);
} //定义真实项目
class RealSubject implements Subject{
public RealSubject(){}
@Override
public String say(String name, int age) {
System.out.println(name+"开始工作");
return name+" "+age;
}
} class MyInvocationHandler implements InvocationHandler{
private Object obj;
public MyInvocationHandler(){}
public MyInvocationHandler(Subject obj){
this.obj = obj;
} public Object bind(Object obj){
this.obj = obj;
return Proxy.newProxyInstance(obj.getClass().getClassLoader(),obj.getClass().getInterfaces(),this);
} @Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("预处理工作");
Object temp = method.invoke(this.obj,args);
System.out.println("后续工作");
return temp;
} }