前言
- 学习设计模式对我们编写可读性强,扩展性好,耦合度低的代码有很大帮助。毕竟谁也不想写或接手垃圾代码。
- 代理模式属于结构型设计模式。在spring中有两个核心模块,其中一个就是AOP切面。它就是使用了动态代理模式对方法进行增强操作。
- 关于代理的定义这里就不在描述了,下面就用官方售票和代理售票的流程模拟三个动态代理实例。
传统代理方案
public class OfficialSell {
public void sellingTickets(Integer price) {
System.err.println("官方售票处收到金额 " + price);
}
}
public class ProxySell {
private OfficialSell officialSell;
public ProxySell(OfficialSell o) {
this.officialSell = o;
}
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动态代理前提是我们必须要有一个接口和接口的实现类
public interface OfficialSell {
void sellingTickets(Integer price);
}
public class OfficialSellImpl implements OfficialSell {
@Override
public void sellingTickets(Integer price) {
System.err.println("官方售票处收到金额 " + price);
}
}
- JDK动态代理主要使用Proxy.newProxyInstance方法创建代理对象实例。三个参数分别是:当前被代理接口的类加载器(目的是使代理类和被代理类用同一类加载器进行加载),被代理类实现的接口列表(这里必须使用接口实现类的实例),InvocationHandler接口的实现类。
public class TestMain {
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动态代理是针对一个没有实现接口的类进行的到动态代理。
public class OfficialSell {
public void sellingTickets(Integer price) {
System.err.println("官方售票处收到金额 " + price);
}
}
- CGLIB动态代理主要使用Enhancer对象创建代理对象实例。需要注入一个被代理类对象和MethodInterceptor接口的实现类。
public class TestMain {
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