【java入门点滴】动态代理模式
简单代理模式,请参考 简单代理模式
动态代理模式
所谓代理,就是需要代理类和被代理类有相同的对外接口或者说成服务,所以代理类一般都必须实现了所有被代理类已实现的接口,因为接口就是制定了一系列对外服务的标准。
正因为动态代理有这样灵活的特性,所以我们在设计动态代理类(DynamicProxy)时不用显式地让它实现与真实主题类(RealSubject)相同的接口(interface),而是把这种实现推迟到运行时。
动态代理模式,核心主要是反射;主要使用到了:
1、java.lang.reflect.InvocationHandler:InvocationHandler接口用来约束调用者实现;
2、java.lang.reflect.Proxy:Proxy类主要用来获取动态代理对象,主要是重写的invoke方法;
动态代理模式
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
/**
* Created by wangzh on 2016/4/21.
* Description: 动态代理的调用处理类
*/
public class HouseSaleInvocationHandler implements InvocationHandler {
// 被代理类的实例
private Object obj = null;
// 将被代理者的实例传进动态代理类的构造函数中
public HouseSaleInvocationHandler(Object obj) {
this.obj = obj;
}
/**
* 生成代理类工厂
*
* @param realObj 真实对象
* @return 返回生成的代理类
* @author com.tiantian
*/
public static Object getProxyInstanceFactory(Object realObj) {
Class<?> classType = realObj.getClass();
ClassLoader classLoader = classType.getClassLoader();
Class<?>[] interfaces = classType.getInterfaces();
InvocationHandler invocationHandler = new HouseSaleInvocationHandler(realObj);
/*
* classLoader : 被代理类的类加载器
* interfaces :被代理类已实现的所有接口,而这些是动态代理类要实现的接口列表
* invocationHandler :用被代理类的实例创建动态代理类的实例,用于真正调用处理程序
*
* return :返回实现了被代理类所实现的所有接口的Object对象,即动态代理,需要强制转型
*/
//获得代理的实例
return Proxy.newProxyInstance(classLoader, interfaces, invocationHandler);
}
/**
* 覆盖InvocationHandler接口中的invoke()方法
* <p>
* 更重要的是,动态代理模式可以使得我们在不改变原来已有的代码结构
* 的情况下,对原来的“真实方法”进行扩展、增强其功能,并且可以达到
* 控制被代理对象的行为,下面的before、after就是我们可以进行特殊
* 代码切入的扩展点了。
* </p>
*
* @param proxy
* @param method
* @param args
* @return return null
* @throws Throwable
*/
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("dynamic invoke before");
Object result = null;
// 除此之外,还可以扩展自有逻辑,比如判定、日志等
result = method.invoke(obj, args);
System.out.println("dynamic invoke after");
return result;
}
}
客户端:
public class BrokerProxyClient {
public static void main(String[] args) {
System.out.println("动态代理测试结果");
// 房主--即真实对象实例
HouseSale masterService = new HouseMasterService();
// 因返回的是Object,需要类型转换
HouseSale dynamicProxy = (HouseSale) HouseSaleInvocationHandler.getProxyInstanceFactory(masterService);
// 方式二,利用instanceof检测
Object obj = HouseSaleInvocationHandler.getProxyInstanceFactory(masterService);
if (obj instanceof HouseSale) {
System.out.println("=====dynamicProxy2 instanceof begin=======");
HouseSale dynamicProxy2 = (HouseSale) obj;
dynamicProxy2.sale();
System.out.println("=====dynamicProxy2 instanceof end=======");
}
dynamicProxy.sale();
System.out.println(dynamicProxy.getClass().getName());
}
}
客户端中,我尝试了两种方式调用;一种是直接强制类型转换;另外一种是利用instanceof进行一次类型检查;目的也是为了更加安全。
输出结果:
动态代理测试结果
=====dynamicProxy2 instanceof begin=======
dynamic invoke before
我是房主,我需要卖房子。
dynamic invoke after
=====dynamicProxy2 instanceof end=======
dynamic invoke before
我是房主,我需要卖房子。
dynamic invoke after
com.sun.proxy.$Proxy0
参考:
http://haolloyin.blog.51cto.com/1177454/333257/
点滴积累,每天进步一点点!O(∩_∩)O~