基于子类的动态代理
通过一张图直观的看出:
所谓的代理模式,其实就是代理真实对象,达到增强真是对象的目的。
例如:上图中我在西安,要向联想北京总公司(真实对象)买电脑,西安有一个北京联想公司的代理商,显然跑去北京买太不划算了,所以可以直接向代理商买,代理商从中赚差价。总公司和代理商直接存在着一些关联,例如代理商需要从总公司进货,代理商的价格不能太高等…
- 静态代理:有一个类文件描述代理模式
- 动态代理:在内存中形成代理类
- 特点:字节码随用随创建,随用随加载
- 作用:不修改源码的基础上,对方法进行增强
动态代理示例:
- 联想总公司
public interface SaleComputer {
public String sale(double money);
public void show();
}
- 西安联想代理商
public class Lenvov implements SaleComputer {
public String sale(double money) {
System.out.println("花了"+money+"钱买电脑");
return "联想电脑...";
}
public void show() {
System.out.println("展示电脑...");
}
}
- 方法执行
public class ProxyTest {
public static void main(String[] args) {
//1.创建真实对象
final Lenvov lenvov = new Lenvov();
//动态增强lenvov对象:
/**
* 参数:
* 1.代理对象类加载器:lenvov.getClass().getClassLoader()
* 用于加载代理对象字节码文件,和被代理对象使用相同的类加载器
* 2.接口数组:保证了真实对象和代理对象实现相同的接口:lenvov.getClass().getInterfaces()
* 3.
*
* 可以强制转为SaleComputer是因为:代理对象和正式对象实现了相同的接口
*/
SaleComputer proxy_sc = (SaleComputer) Proxy.newProxyInstance(lenvov.getClass().getClassLoader(),
lenvov.getClass().getInterfaces(),
new InvocationHandler() {
/**
* 代理逻辑编写的方法:每一次代理对象调用方法,都会执行这个函数
* @param proxy: 代理对象=proxy_sc
* @param method :代理对象调用的方***被封装成Method对象
* @param args :代理对象调用的方法实际传递的参数
* @return :代理对象调用方法时的返回值
* @throws Throwable
*/
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("invoke...被执行了");
if (method.getName().equals("sale")){
System.out.println("代理商专车接送过来买电脑...");
//1.增强参数
double money = (Double)args[0];
money *=0.85;
//2.增强方法执行的方法体
String invoke = method.invoke(lenvov, money); //返回电脑
System.out.println("代理商专车接送回去...");
//3.增强返回值
return invoke+"鼠标垫"; //返回代理对执行的结果
}else {
Object invoke = method.invoke(lenvov, args);
return null;
}
}
});
//3.调用方法
String sale = proxy_sc.sale(7000);
System.out.println(sale);
//proxy_sc.show();
}
}
内部逻辑就是用户给出7000块去买代理商电脑,代理商对收到的7000元进行85折,自己回收15%,85%付给了联想公司,所以这边输出:花了5950买电脑是其实是代理商向联系公司买电脑花的钱,而不是用户向联想公司花的钱,被赚差价了。
invoke函数返回值是代理对象的执行结果。
不基于子类的动态代理
- 被代理类
public class Lenvov {
public String sale(double money) {
System.out.println("花了"+money+"钱买电脑");
return "联想电脑...";
}
public void show() {
System.out.println("展示电脑...");
}
}
- 测试方法:
/**
* 不基于子类的动态代理
*
*/
public class ProxyTest {
public static void main(String[] args) {
//1.创建真实对象
final Lenvov lenvov = new Lenvov();
//动态增强lenvov对象:
Lenvov proxy_lenvov = (Lenvov)Enhancer.create(lenvov.getClass(),
new MethodInterceptor() {
/**
* 执行被代理对象的任何方法都会经过该方法
* 可以强制转为SaleComputer是因为:代理对象和正式对象实现了相同的接口
* @param proxy :代理对象
* @param method:代理对象执行的方***被封装成Method方法
* @param args :代理对象调用的方法实际传递的参数
* @param methodProxy:当前执行对象的代理方法
* @return :代理对象调用方法时的返回值
* @throws Throwable
*/
public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
System.out.println("invoke...被执行了");
if (method.getName().equals("sale")){
System.out.println("代理商专车接送过来买电脑...");
//1.增强参数
double money = (Double)args[0];
money *=0.85;
//2.增强方法执行的方法体
Object invoke = method.invoke(lenvov, money); //返回电脑
System.out.println("代理商专车接送回去...");
//3.增强返回值
return invoke+"鼠标垫"; //返回代理对执行的结果
}else {
Object invoke = method.invoke(lenvov, args);
return null;
}
}
});
String sale = proxy_lenvov.sale(10000);
System.out.println(sale);
}
}