1.什么是代理?
看图吧
2.JAVA中基于接口的动态代理
一个定义了生产商应该干什么活的接口
public interface IProductor {
/**
* 生产
* @param money
*/
public void saleProduct(double money);
/**
* 售后
* @param money
*/
public void afterService(double money);
}
一个生产商
public class Producter implements IProductor{
/**
* 生产
* @param money
*/
public void saleProduct(double money){
System.out.println("销售产品,并赚了" + money + "钱");
}
/**
* 售后
* @param money
*/
public void afterService(double money){
System.out.println("提供了售后服务,并赚了" + money + "钱");
}
}
我们的小明
public class Client {
public static void main(final String[] args) {
//定义一个生产商
final Producter producter = new Producter();
//代理对象 proxyProductor来找生产商做代理了
/**
* newProxyInstance方法的参数:
* ClassLoader:用于加载代理对象字节码,和被代理对象使用相同的类加载器,代理谁使用谁的类加载器
* Class[]:字节码数组,让代理对象和被代理对象有相同的方法,代理谁就写谁
* InvocationHandler:用于提供增强的代码,它是让我们写如何代理,我们一般都是写一个该接口的实现类,
* 通常情况下都是匿名内部类,但不是必须的,此接口的实现类都是谁用谁写
*/
//通过Proxy.的newProxyInstance创建一个Productor的代理
IProductor proxyProductor =(IProductor) Proxy.newProxyInstance(producter.getClass().getClassLoader(),
producter.getClass().getInterfaces(),
new InvocationHandler() {
/**
* 执行被代理对象的任何接口方法都会经过该方法,拦截接口中的方法
* @param o 代理对象的引用
* @param method 当前执行的方法
* @param objects 当前执行方法所需的参数
* @return 和被代理对象有相同的返回值
* @throws Throwable
*/
public Object invoke(Object o, Method method, Object[] objects) throws Throwable {
//提供增强的代码
Object returnValue = null;
//1,获取方法执行的参数
Double money = (Double) objects[0];
//2.判断当前方法是不是销售
if("saleProduct".equals(method.getName())){
//使用了代理,在生产商售卖的时候,代理从中间抽取了20%的利润
returnValue = method.invoke(producter,money * 0.8);
}
return returnValue;
}
});
proxyProductor.saleProduct(1000);
}
}
打印
销售产品,并赚了800.0钱
详细说明
- 动态代理
- 特点:字节码随用随创建,随用岁加载,
- 作用:在不修改源码的基础上对源码进行增强
- 分类:基于接口的动态代理, 基于子类的动态代理
- 涉及的类:Proxy
- 提供者:JDK官方
- 如何创建代理对象:使用Proxy中的newProxyInstance方法
- 创建基于接口的代理对象的要求:
* 被代理类最少实现一个接口,如果没有则不能使用
* newProxyInstance方法的参数:
* ClassLoader:用于加载代理对象字节码,和被代理对象使用相同的类加载器,代理谁使用谁的类加载器
* Class[]:字节码数组,让代理对象和被代理对象有相同的方法,代理谁就写谁
* InvocationHandler:用于提供增强的代码,它是让我们写如何代理,我们一般都是写一个该接口的实现类,
* 通常情况下都是匿名内部类,但不是必须的,此接口的实现类都是谁用谁写
2.JAVA中基于子类的动态代理
基于子类的代理需要第三方jar包 cglib
生产商
import com.echo.proxy.IProductor;
public class Producter{
/**
* 生产
* @param money
*/
public void saleProduct(double money){
System.out.println("销售产品,并赚了" + money + "钱");
}
/**
* 售后
* @param money
*/
public void afterService(double money){
System.out.println("提供了售后服务,并赚了" + money + "钱");
}
}
小明
public class Client {
public static void main(final String[] args) {
final Producter producter = new Producter();
Producter cglibProductor = (Producter)Enhancer.create(producter.getClass(), new MethodInterceptor() {
/**
* 执行被代理对象的任何方法都会经过该方法
* @param o 代理对象的引用
* @param method 当前执行的方法
* @param objects 当前执行方法所需的参数
* @param methodProxy 当前执行方法的代理对象
* @return
* @throws Throwable
*/
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
//提供增强的代码
Object returnValue = null;
//1,获取方法执行的参数
Double money = (Double) objects[0];
//2.判断当前方法是不是销售
if("saleProduct".equals(method.getName())){
returnValue = method.invoke(producter,money * 0.8);
}
return returnValue;
}
});
cglibProductor.saleProduct(1000);
}
}
详解
* 涉及的类:Enhancer
* 提供者:第三方cglib库
* 如何创建代理对象:使用Enhancer类中的create方法
* 创建代理对象的要求: 被代理类不能是最终类
* create方法的参数:
Class字节码:用于指定被代理对象的字节码
callback:用于提供增强的代码
它是让我们写如何代理,我们一般都是写一个该接口的实现类,通常情况下都是匿名内部类,但不是必须的,此接口的实现类都是谁用谁写,我们一般写的都是该接口的子接口实现类MethodInterceptor
来源:CSDN
作者:EEEEEEcho
链接:https://blog.csdn.net/EEEEEEcho/article/details/104783567