概述
什么是代理。个人认为就是我们常说的:中间商赚差价。
在以往的消费模式中,往往都是消费者直接联系生产者,但这个时候生产者又要生产产品、又要保证售后。给生产者带来了一个非常大的一个压力。因此,随着时代进步,中间商这个群体出现了,他们联系生产者,这个时候生产者只负责生产东西,中间商负责售后。保证了效率,消费者的权益也得到了保障。
特点
字节码随用随创建,随用随加载。
作用
在不修改源码的情况下,对功能进行一个增强。
分类
- 基于接口的动态代理
- 基于子类的动态代理
基于接口的动态代理
- 定义一个接口
IProducer
,用于实现类使用
package one_interface;
public interface IProducer {
/**
* 销售
*/
public void sale(double money);
/**
* 售后
*/
public void service(double money);
}
- 定义一个类
Producer
,实现该接口
package one_interface;
public class Producer implements IProducer{
/**
* 销售
*/
public void sale(double money){
System.out.println("卖了东西,拿到:"+money);
}
/**
* 售后
*/
public void service(double money){
System.out.println("由于质量出现问题,包修、换,花了:"+money);
}
}
- 编写简易生产者、消费者用于中间商赚差价主函数
client
- 使用
proxy
的一个静态方法newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h)
- 具体参数如下表所示
- 使用
参数 | 含义 | 作用 |
---|---|---|
ClassLoader | 类加载器 | 它是用于加载代理对象字节码的。和被代理对象使用相同的类加载器。固定写法。 |
Class<?>[] | 字节码数组 | 它是用于让代理对象和被代理对象有相同方法。固定写法。 |
InvocationHandler | 提供增强的代码 | 它是让我们写如何代理。我们一般都是些一个该接口的实现类,通常情况下都是匿名内部类,但不是必须 |
package one_interface;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
public class Client {
public static void main(String[] args) {
final Producer producer = new Producer();
// 中间商赚差价
IProducer iProducer = (IProducer) Proxy.newProxyInstance(producer.getClass().getClassLoader(),
producer.getClass().getInterfaces(),
new InvocationHandler() {
/**
* 作用:执行被代理对象的所有接口方法,都会经过这里。执行invoke方法
* @param proxy 代理对象的引用
* @param method 当前执行方法
* @param args 当前执行方法的参数
* @return 和被代理对象方法有相同的返回值
* @throws Throwable
*/
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
// 开始赚差价
Object obj = null;
// 中间商。从消费者拿到钱。自己收一部分,再给生产者
if("sale".equals(method.getName())){
Double money = (Double)args[0];
obj = method.invoke(producer,money*0.8);
}
return obj;
}
});
iProducer.sale(10000);
}
}
基于子类的动态代理
- 需要依赖cglib包,因此要导入
建议使用maven工程,联网之后检索配置下有无该包,如果没有即可自动导入。如下所示:
<dependencies>
<dependency>
<groupId>cglib</groupId>
<artifactId>cglib</artifactId>
<version>3.2.4</version>
</dependency>
</dependencies>
- 直接写类。无需继承。如下所示:
package two_ziclass;
public class Producer{
/**
* 销售
*/
public void sale(double money){
System.out.println("卖了东西,拿到:"+money);
}
/**
* 售后
*/
public void service(double money){
System.out.println("由于质量出现问题,包修、换,花了:"+money);
}
}
- 编写简易生产者、消费者用于中间商赚差价主函数
client
- 使用
Enhancer
的一个静态方法create(Class type, Callback callback)
- 具体参数如下表所示
- 使用
参数 | 含义 | 作用 |
---|---|---|
Class | 字节码 | 他是用于指定被代理对象的字节码 |
Callback | 提供增强的代码 | 让我们写如何代理。一般使用该接口的实现类:MethodInterceptor |
package two_ziclass;
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
import java.lang.reflect.Method;
public class Client {
public static void main(String[] args) {
final Producer producer = new Producer();
// 中间商赚差价
Producer cglibProducer = (Producer) Enhancer.create(producer.getClass(), new MethodInterceptor() {
/**
* 作用:执行被代理对象的所有方法,都会经过这里。执行intercept方法
* @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 obj = null;
// 中间商。从消费者拿到钱。自己收一部分,再给生产者
if("sale".equals(method.getName())){
Double money = (Double)objects[0];
obj = method.invoke(producer,money*0.8);
}
return obj;
}
});
cglibProducer.sale(20000);
}
}