- 学习设计模式对我们编写可读性强,扩展性好,耦合度低的代码有很大帮助。比较谁也不想写或接手垃圾代码。
- 代理模式属于结构型设计模式。在spring中有两个核心模块,其中一个就是AOP切面。它就是使用了动态代理模式对方法进行增强操作。关于代理的定义这里就不在描述了,下面就用官方售票和代理售票的流程模拟三个动态代理实例。
传统代理方案
/**
* 官方卖票
*
* @Author: ZRH
* @Date: 2021/2/4 11:46
*/
public class OfficialSell {
/**
* 卖票方法
*/
public void sellingTickets(Integer price) {
System.err.println("官方售票处收到金额 " + price);
}
}
/**
* 代理售票
*
* @Author: ZRH
* @Date: 2021/2/4 11:54
*/
public class ProxySell {
private OfficialSell officialSell;
/**
* 构造一个官方售票对象
*
* @param o
*/
public ProxySell(OfficialSell o) {
this.officialSell = o;
}
/**
* 售票方法
*
* @param price
*/
public void sellingTickets(Integer price) {
System.err.println("代理售票处收费 200");
Integer money = price - 200;
officialSell.sellingTickets(money);
}
}
/**
* 传统代理方案
*
* @param args
*/
public static void main(String[] args) {
Integer price = 1000;
// 创建一个官方售票对象
OfficialSell officialSell = new OfficialSell();
// 创建一个代理售票对象,把官方售票对象放进去
ProxySell proxySell = new ProxySell(officialSell);
System.err.println("用户购票金额 " + price);
proxySell.sellingTickets(price);
}
用户购票金额 1000
代理售票处收费 200
官方售票处收到金额 800
JDK动态代理方案
- 使用JDK动态代理前提是我们必须要有一个接口和接口的实现类
/**
* 官方卖票
*
* @Author: ZRH
* @Date: 2021/2/4 11:46
*/
public interface OfficialSell {
/**
* 卖票方法
*/
void sellingTickets(Integer price);
}
/**
* 官方卖票
*
* @Author: ZRH
* @Date: 2021/2/4 11:46
*/
public class OfficialSellImpl implements OfficialSell {
/**
* 卖票方法
*/
@Override
public void sellingTickets(Integer price) {
System.err.println("官方售票处收到金额 " + price);
}
}
- JDK动态代理主要使用Proxy.newProxyInstance方法创建代理对象实例。三个参数分别是:当前被代理接口的类加载器(目的是使代理类和被代理类用同一类加载器进行加载),被代理类实现的接口列表(这里必须使用接口实现类的实例),InvocationHandler接口的实现类。
/**
* @Author: ZRH
* @Date: 2021/2/4 11:56
*/
public class TestMain {
/**
* JDK动态代理方案
*
* @param args
*/
public static void main(String[] args) {
Integer price = 1000;
System.err.println("用户购票金额 " + price);
// 定义代理类的类加载器,代理类的接口列表,需要增强代理的实现
OfficialSell o = (OfficialSell) Proxy.newProxyInstance(OfficialSell.class.getClassLoader(),
new OfficialSellImpl().getClass().getInterfaces(),
(proxy, method, args1) -> {
if ("sellingTickets".equals(method.getName())) {
System.err.println("代理售票处收费 200");
Integer price1 = (Integer) args1[0];
Integer money = price1 - 200;
return method.invoke(new OfficialSellImpl(), money);
}
return null;
});
o.sellingTickets(price);
}
}
用户购票金额 1000
代理售票处收费 200
官方售票处收到金额 800
CGLIB动态代理方案
- CGLIB动态代理是针对一个没有实现接口的类进行的到动态代理。
/**
* 官方卖票
*
* @Author: ZRH
* @Date: 2021/2/4 11:46
*/
public class OfficialSell {
/**
* 卖票方法
*/
public void sellingTickets(Integer price) {
System.err.println("官方售票处收到金额 " + price);
}
}
- CGLIB动态代理主要使用Enhancer对象创建代理对象实例。需要注入一个被代理类对象和MethodInterceptor接口的实现类。
/**
* @Author: ZRH
* @Date: 2021/2/4 11:56
*/
public class TestMain {
/**
* CGLIB动态代理方案
*
* @param args
*/
public static void main(String[] args) {
Integer price = 1000;
System.err.println("用户购票金额 " + price);
final Enhancer enhancer = new Enhancer();
// 代理类对象
enhancer.setSuperclass(OfficialSell.class);
// 需要增强代理的实现
enhancer.setCallback((MethodInterceptor) (o, method, objects, methodProxy) -> {
if ("sellingTickets".equals(method.getName())) {
System.err.println("代理售票处收费 200");
Integer price1 = (Integer) objects[0];
Integer money = price1 - 200;
return method.invoke(new OfficialSell(), money);
}
return null;
});
OfficialSell officialSell = (OfficialSell) enhancer.create();
officialSell.sellingTickets(price);
}
}
用户购票金额 1000
代理售票处收费 200
官方售票处收到金额 800