共计 2442 个字符,预计需要花费 7 分钟才能阅读完成。
紧接着上节,为了解决静态代理的问题,出现了动态代理,先上代码:
/**
* 动态代理
*/
public class DynamicProxyCompanyC implements InvocationHandler {
// 被代理的对象,即真实对象
private Object factory;
public Object getFactory() {
return factory;
}
public void setFactory(Object factory) {
this.factory = factory;
}
// 通过 proxy 获取动态代理的对象
public Object getProxyInstance() {
// 第三个参数是 InvocationHandler,传入自身说明此 proxy 对象是和自身的 invoke 方法合作的,代理对象方法调用会经过下面 invoke 的增强
return Proxy.newProxyInstance(factory.getClass().getClassLoader(), factory.getClass().getInterfaces(), this);
}
@Override
/** 通过动态代理对象对方法进行增强
* @param proxy 代理对象
* @param method 要增强的方法(拦截的方法)
* @param args 方法参数
*/
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
dosomeThingBefore();
Object ret = method.invoke(factory, args);// 通过反射机制调用方法
dosomeThingAfter();
return ret;
}
public void dosomeThingBefore() {
System.out.println(“ 售前服务,负责产品调研,兴趣爱好 ”);
}
public void dosomeThingAfter() {
System.out.println(“ 售后服务,包装丶送货上门一条龙服务 ”);
}
}
假设动态代理是一个代购公司,私有变量 Object factory 为动态生成的具体的真实对象,可代购对应的产品
测试类:
public class Proxytest {
public static void main(String[] args) {
// 代购公司 C,负责代购所有产品
DynamicProxyCompanyC proxy = new DynamicProxyCompanyC();
// 日本有家 A 公司生产男性用品
ManToolFactory dogToolFactory = new AManFactory();
// 代购 A 公司的产品
proxy.setFactory(dogToolFactory);
// 创建 A 公司的代理对象
ManToolFactory proxyObject = (ManToolFactory) proxy.getProxyInstance();
// 代理对象完成代购男性用品
proxyObject.saleManTool(“D”);
System.out.println(“————–“);
// 日本有家 B 公司生产女性用品
WomanToolFactory womanToolFactory = new BWomanFactory();
// 代购 B 公司的产品
proxy.setFactory(womanToolFactory);
// 创建 B 公司的代理对象
WomanToolFactory proxyObject1 = (WomanToolFactory) proxy.getProxyInstance();
// 代理对象完成代购女性用品
proxyObject1.saleWomanTool(1.8);
}
}
// 售前服务,负责产品调研,兴趣爱好
// A 工厂出售男性用品,D 罩杯
// 售后服务,包装丶送货上门一条龙服务
// ————–
// 售前服务,负责产品调研,兴趣爱好
// B 工厂生产女性用品, 长度 1.8 米
// 售后服务,包装丶送货上门一条龙服务
动态代理解决了上节说的开闭原则,那么接下来我们要解密动态代理的原理,重点类 DynamicProxyCompanyC:1. 实现了 InvocationHandler 接口;2. 通过 proxy 获取动态代理的对象。根据我们此例子里面来说,动态代理就类似一个代购公司,可代购所有产品,需要购买哪个产品的时候就实例化一个真实对象(如测试类需要男性用品则将接口引用指向真实对象 AManFactory),根据真实对象创建代理对象来执行具体的方法,图解如下:
Proxy: 接下来我们先初步看一下 JDK 里面的 Proxy 这个源码
这个注释是说 Proxy 提供个一个静态方法来创建代理类和代理实例,它也是所有由此方法创建的代理类的父类。静态方法创建代理实例即方法 newProxyInstance(ClassLoader loader,Class<?>[]interfaces,InvocationHandler h);
InvocationHandler :InvocationHandler 是一个接口,定义了 invoke(Object proxy, Method method, Object[] args) 方法
总的来说 Proxy 专门负责 new 一个实例(真实对象),而具体方法做什么,业务怎样增强就由 InvocationHandler(抽象对象) 的 invoke 方法(抽象对象即接口定义的方法)来决定。
接下来我们要搞清楚动态代理的底层原理,首先我们调试一下,会发现 ManToolFactory proxyObject = (ManToolFactory) proxy.getProxyInstance() 中创建的 proxyObject 对象类名是 &Proxy0,是 ManToolFactory 接口的实现类。但是我们项目工程里面却没有 &Proxy0 这个类,那它究竟是怎么出现的,下节讲解。