5.代理模式
1.代理模式是给原对象生成一个代理对象,并由代理对象控制原对象的使用,但是在使用原对象的过程中可以做一些额外的事情。这个和我们生活中的中介类似,如房产中介,票务中介等等。代理模式的优点是不直接调用原对象而是调用代理对象,这样可以可以起到一定保护作用和解耦作用,另外最重要的是在代理对象调用过程中可以做额外的操作。缺点在于要为每一个对象去创建代理对象的话会对性能有一定程度上的牺牲。最常见的示例是spring的AOP就是通过代理来实现,他在运行过程中动态生成代理对象,并可以增加前置操作,后置操作,也即通知。代理模式分为动态代理和静态代理,动态代理是在运行过程中生成动态生成代理对象,静态代理是在编码的时候由开发人员手动创建代理对象或者通过特定的工具创建代理对象,在程序运行之前代理对象已经存在。动态代理常见的有JDK动态代理和CGLIB动态代理。
2.静态代理。下面以买车票为例实现静态代理,买车票可以自行购买,也可以通过携程帮我们买,所以携程就是一个代理对象,我们把账号和密码给他,由他帮我们执行购买这个动作,但是在购买之前我们需要预约,购买以后需要付手续费。
package com.java.dp.proxy; /** * @Author lizhilong * @create 2019/12/3 13:40 * @desc */ public interface BuyTicket { void buyTickt(); }
package com.java.dp.proxy; /** * @Author lizhilong * @create 2019/12/3 13:42 * @desc 原对象 */ public class UserByTicket implements BuyTicket { @Override public void buyTickt() { System.out.println("购买火车票"); } }
package com.java.dp.proxy; /** * @Author lizhilong * @create 2019/12/3 13:43 * @desc 代理对象 */ public class XiechengProxy implements BuyTicket { private BuyTicket buyTicket; public XiechengProxy(BuyTicket buyTicket){ this.buyTicket = buyTicket; } @Override public void buyTickt() { beforeBuy(); buyTicket.buyTickt(); afterBuy(); } private void beforeBuy(){ System.out.println("购买火车票之前需要在携程app预约"); } private void afterBuy(){ System.out.println("购买成功要支付手续费"); } }
package com.java.dp.proxy; /** * @Author lizhilong * @create 2019/12/3 13:46 * @desc */ public class ProxyMain { public static void main(String[] args) { BuyTicket buyTicket = new XiechengProxy(new UserByTicket()); buyTicket.buyTickt(); } }
购买火车票之前需要在携程app预约
正常购买火车票
购买成功要支付手续费
3.JDK实现动态代理
在静态代理的基础上实现JDK动态代理,JDK动态代理首先需要写一个动态代理处理器实现InvocationHandler接口,而且JDK动态代理要求被代理的类必须实现接口。
package com.java.dp.proxy; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; /** * @Author lizhilong * @create 2019/12/3 14:14 * @desc */ public class JDKProxy implements InvocationHandler { private Object object; public JDKProxy(Object object){ this.object = object; } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { beforeBuy(); Object result = method.invoke(object,args); afterBuy(); return result; } private void beforeBuy(){ System.out.println("购买火车票之前需要在携程app预约"); } private void afterBuy(){ System.out.println("购买成功要支付手续费"); } }
package com.java.dp.proxy; import java.lang.reflect.Proxy; /** * @Author lizhilong * @create 2019/12/3 13:46 * @desc */ public class ProxyMain {
public static void main(String[] args) {
BuyTicket buyTicket = new UserByTicket();
BuyTicket buyTicketProxy = (BuyTicket) Proxy.newProxyInstance(buyTicket.getClass().getClassLoader(),new Class[]{BuyTicket.class},new JDKProxy(buyTicket));
buyTicketProxy.buyTickt();
}
}
4.CGlib 实现动态代理
cglib 实现动态代理不需要实现接口,是通过继承的方式生成子类来实现的。基于springboot2.1.1 release
package com.java.dp.proxy; import org.springframework.cglib.proxy.Enhancer; import org.springframework.cglib.proxy.MethodInterceptor; import org.springframework.cglib.proxy.MethodProxy; import java.lang.reflect.Method; /** * @Author lizhilong * @create 2019/12/3 14:37 * @desc */ public class CGLibProxy implements MethodInterceptor { private Object object; public Object getPorxyInstance (Object object){ this.object = object; Enhancer enhancer = new Enhancer(); enhancer.setSuperclass(this.object.getClass()); enhancer.setCallback(this); return enhancer.create(); } @Override public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable { beforeBuy(); Object result = methodProxy.invokeSuper(o,objects); afterBuy(); return result; } private void beforeBuy(){ System.out.println("购买火车票之前需要在携程app预约"); } private void afterBuy(){ System.out.println("购买成功要支付手续费"); } }
package com.java.dp.proxy; /** * @Author lizhilong * @create 2019/12/3 13:46 * @desc */ public class ProxyMain { public static void main(String[] args) { CGLibProxy cgLibProxy = new CGLibProxy(); BuyTicket buyTicket = new UserByTicket(); BuyTicket cglibProxy = (BuyTicket) cgLibProxy.getPorxyInstance(buyTicket); cglibProxy.buyTickt(); } }