您的位置:首页 > 其它

设计模式-动态代理模式

2017-03-16 17:27 253 查看

说明:

动态代理(Dynamic Proxy):相比前一篇文章所实现的代理模式(静态),动态代理具有更强的灵活性,因为它不用在我们设计实现的时候就指定某一个代理类来代理哪一个被代理对象,我们可以把这种指定延迟到程序运行时由JVM来实现。

我们知道,所谓代理,就是需要代理类和被代理类有相同的对外接口或者说成服务,所以代理类一般都必须实现了所有被代理类已实现的接口,因为接口就是制定了一系列对外服务的标准。

正因为动态代理有这样灵活的特性,所以我们在设计动态代理类(DynamicProxy)时不用显式地让它实现与真实主题类(RealSubject)相同的接口(interface),而是把这种实现推迟到运行时。

为了能让DynamicProxy类能够在运行时才去实现RealSubject类已实现的一系列接口并执行接口中相关的方法操作,需要让DynamicProxy类实现JDK自带的java.lang.reflect.InvocationHandler接口,该接口中的invoke()方法能够让DynamicProxy实例在运行时调用被代理类的“对外服务”,即调用被代理类需要对外实现的所有接口中的方法,也就是完成对真实方法的调用,Java帮助文档中称这些真实方法为处理程序。

按照上面所述,我们肯定必须先把被代理类RealSubject已实现的所有interface都加载到JVM中,不然JVM怎么能够找到这些方法呢?明白了这个道理,那么我们就可以创建一个被代理类的实例,获得该实例的类加载器ClassLoader。

所谓的类加载器ClassLoader,就是具有某个类的类定义,即类的内部相关结构(包括继承树、方法区等等)。

更重要的是,动态代理模式可以使得我们在不改变原来已有的代码结构的情况下,对原来的“真实方法”进行扩展、增强其功能,并且可以达到控制被代理对象的行为的目的。请详看下面代码中的DynamicProxy类,其中必须实现的invoke()方法在调用被代理类的真实方法的前后都可进行一定的特殊操作。这是动态代理最明显的优点。

实现:

1.创建一个接口

/**
* 接口
* @author niewei
*
*/
public interface Service {
public String say();//打一个招呼
public void hello();//说一句话
}


2.创建一个实现类:

/**
* 接口实现类
*
* @author niewei
*
*/
public class ServiceBean implements Service {
private String name;

public ServiceBean() {}

public ServiceBean(String name) {
this.name = name;
}

@Override
public String say() {
System.out.println("你来了?等了你好久了。");
return "你好!";
}

@Override
public void hello() {
System.out.println("welcome!");
}

public String getName() {
return name;
}

}


3.创建代理类

import java.lang.reflect.InvocationHandler;

import java.lang.reflect.Method;

import java.lang.reflect.Proxy;

/**
* 代理工厂
*
* @author niewei
*
*/
public class ServiceProxy implements InvocationHandler {
private Object targetObj;

public Object caeateProxyIntance(Object targetObj) {
this.targetObj = targetObj;
return Proxy.newProxyInstance(this.targetObj.getClass().getClassLoader(),
this.targetObj.getClass().getInterfaces(), this);
}

@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("执行前:---------------------");
Object obj = method.invoke(this.targetObj, args);
System.out.println("执行后:---------------------");
return obj;
}

}


4.测试

/**
* 测试
* @author niewei
*
*/
public class Test {
public static void main(String[] args) {
//创建代理工厂对象
ServiceProxy pro=new ServiceProxy();
//创建bean
ServiceBean bean=new ServiceBean("zhangke");
//创建代理
Service service=(Service) pro.caeateProxyIntance(bean);
//打招呼说话!
String say=service.say();
System.out.println(say);
//service.hello();
}
}


运行结果如下:
执行前:---------------------
你来了?等了你好久了。
执行后:---------------------
你好!
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: