浅谈Java反射机制(二)

这一篇将会讲到利用java的反射机制而设计的动态代理模式。



•代理模式一般涉及到的角色有
抽象角色:声明真实对象和代理对象的共同接口。
代理角色:代理对象角色内部含有对真实对象的引用,从而可以操作真实对象,同时代理对象提供与真实对象相同的接口以便在任何时刻都能代替真实对象。同时,代理对象可以在执行真实对象操作时,附加其他的操作,相当于对真实对象进行封装。
真实角色:代理角色所代表的真实对象,是我们最终要引用的对象。


如果像上面描述那样,每个代理角色“都持有对真实对象的引用,并同时提供与真实对象相同的接口一遍在任何时刻代替真实对象”的话,那么我们可以很容易想象,随着需要代理的类增多,很快就会出现“类爆炸”的现象。

动态代理,是指在不知道真实角色的情况下,去调用正确的方法。

其实很简单,不要想得太复杂了,就是利用监听传进来的对象,在调用此方法时,在这方法之间做一个调用。

好啦,直接代码吧:

首先是抽象角色

[java] view plaincopyprint?package com.insigma.dymic; 
 
public interface Subject { 
    public void request(); 


package com.insigma.dymic;

public interface Subject {
public void request();
}

真实角色,就直接实现这接口就可以了

[java] view plaincopyprint?package com.insigma.dymic; 
 
public class RealSubject implements Subject{ 
 
    @Override 
    public void request() { 
        System.out.println("RealSubject do this"); 
    } 
 


package com.insigma.dymic;

public class RealSubject implements Subject{

@Override
public void request() {
System.out.println("RealSubject do this");
}

}

代理角色:



[java] view plaincopyprint?package com.insigma.dymic; 
 
import java.lang.reflect.InvocationHandler; 
import java.lang.reflect.Method; 
 
public class DynamicSubject implements InvocationHandler{ 
     
    private Object sub; 
     
    public DynamicSubject(){ 
         
    } 
     
    public DynamicSubject(Object object){ 
        sub = object; 
    } 
     
    @Override 
    public Object invoke(Object proxy, Method method, Object[] args) 
            throws Throwable { 
        System.out.println("before calling " + method); 
        method.invoke(sub, args); 
        System.out.println("after calling " + method); 
         
        return null; 
    } 
     


package com.insigma.dymic;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;

public class DynamicSubject implements InvocationHandler{

private Object sub;

public DynamicSubject(){

}

public DynamicSubject(Object object){
sub = object;
}

@Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
System.out.println("before calling " + method);
method.invoke(sub, args);
System.out.println("after calling " + method);

return null;
}

}

使用代理角色的客户端:

[java] view plaincopyprint?package com.insigma.app; 
 
import java.lang.reflect.InvocationHandler; 
 
import com.insigma.dymic.DynamicSubject; 
import com.insigma.dymic.ProxyUtil; 
import com.insigma.dymic.RealSubject; 
import com.insigma.dymic.Subject; 
 
public class DynamicProxyApp { 
    public static void main(String[] args) { 
        Subject sub = new RealSubject(); 
        sub = (Subject) ProxyUtil.getInstance(sub); 
        sub.request(); 
    } 


package com.insigma.app;

import java.lang.reflect.InvocationHandler;

import com.insigma.dymic.DynamicSubject;
import com.insigma.dymic.ProxyUtil;
import com.insigma.dymic.RealSubject;
import com.insigma.dymic.Subject;

public class DynamicProxyApp {
public static void main(String[] args) {
Subject sub = new RealSubject();
sub = (Subject) ProxyUtil.getInstance(sub);
sub.request();
}
}


客户端的工具类:

[java] view plaincopyprint?package com.insigma.dymic; 
 
import java.lang.reflect.Constructor; 
import java.lang.reflect.InvocationHandler; 
import java.lang.reflect.InvocationTargetException; 
import java.lang.reflect.Proxy; 
 
public class ProxyUtil { 
    public static Object getInstance(Object obj){ 
        InvocationHandler ds = new DynamicSubject(obj); 
        Class cls = obj.getClass(); 
         
        Class c = Proxy.getProxyClass(cls.getClassLoader(), cls.getInterfaces()); 
        try { 
            Constructor cons = c.getConstructor(new Class[]{InvocationHandler.class}); 
            obj = cons.newInstance(new Object[]{ds}); 
        } catch (SecurityException e) { 
            e.printStackTrace(); 
        } catch (NoSuchMethodException e) { 
            e.printStackTrace(); 
        } catch (IllegalArgumentException e) { 
            e.printStackTrace(); 
        } catch (InstantiationException e) { 
            e.printStackTrace(); 
        } catch (IllegalAccessException e) { 
            e.printStackTrace(); 
        } catch (InvocationTargetException e) { 
            e.printStackTrace(); 
        } 
         
        return obj; 
         
    } 


package com.insigma.dymic;

import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Proxy;

public class ProxyUtil {
public static Object getInstance(Object obj){
InvocationHandler ds = new DynamicSubject(obj);
Class cls = obj.getClass();

Class c = Proxy.getProxyClass(cls.getClassLoader(), cls.getInterfaces());
try {
Constructor cons = c.getConstructor(new Class[]{InvocationHandler.class});
obj = cons.newInstance(new Object[]{ds});
} catch (SecurityException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}

return obj;

}
}



其实理清思路之后很简单,整一个测试的手敲代码连50行都没有。关键是要自己去想,自己想明白的才是你理解到的。

猜你喜欢

转载自20120923lina.iteye.com/blog/1692020