为某一个对象创建一个代理对象,程序不直接用原本的对象,而是由创建的代理对象来控制原对象,通过代理类这中间一层,能有效控制对委托类对象的直接访问,也可以很好地隐藏和保护委托类对象,同时也为实施不同控制策略预留了空间
由程序创建或特定工具自动生成源代码,在程序运行前,代理类的.class文件就已经存在
通过将目标类与代理类实现同一个接口,让代理类持有真实类对象,然后在代理类方法中调用真实类方法,在调用真实类方法的前后添加我们所需要的功能扩展代码来达到增强的目的。
代理使客户端不需要知道实现类是什么,怎么做,而客户端只需知道代理即可
方便增加功能,扩展业务逻辑
代理类中常出现大量冗余的代码,非常不利于扩展和维护
如果接口增加一个方法,除了所有实现类需要实现这个方法外,所有代理类也需要实现此方法。增加了代码维护的复杂度
package net.cybclass.sp.service; /** * @author: wangxiaobo * @create: 2020-10-04 22:33 **/ public class PayServiceImpl implements PayService { @Override public String callback(String outTradeNo) { System.out.println("目标类 PayServiceImpl 回调 方法 callback"); return outTradeNo; } @Override public int save(int userId, int productId) { System.out.println("目标类 PayServiceImpl 回调 方法 save"); return productId; } }
StaticProxyPayServiceImpl.java(接口实现类,静态代理)
package net.cybclass.sp.proxy; import net.cybclass.sp.service.PayService; /** * @author: wangxiaobo * @create: 2020-10-04 22:45 **/ public class StaticProxyPayServiceImpl implements PayService { private PayService payService; public StaticProxyPayServiceImpl(PayService payService) { this.payService = payService; } @Override public String callback(String outTradeNo) { System.out.println("StaticProxyPayServiceImpl callback begin"); String result=payService.callback(outTradeNo); System.out.println("StaticProxyPayServiceImpl callback end"); return result; } @Override public int save(int userId, int productId) { System.out.println("StaticProxyPayServiceImpl save begin"); int id = payService.save(userId, productId); System.out.println("StaticProxyPayServiceImpl save end"); return id; }package net.cybclass.sp.test; import net.cybclass.sp.proxy.JDKProxy; import net.cybclass.sp.proxy.StaticProxyPayServiceImpl; import net.cybclass.sp.service.PayService; import net.cybclass.sp.service.PayServiceImpl; /** * @author: wangxiaobo * @create: 2020-10-04 22:48 **/ public class ProxyTest { public static void main(String[] args) { PayService payService = new StaticProxyPayServiceImpl (new PayServiceImpl ()); payService.save (234,567); // JDKProxy jdkProxy = new JDKProxy (); // PayService payService = (PayService) jdkProxy.newProxyInstance (new PayServiceImpl ()); // payService.callback ("hello wrod"); } }
运行:
在程序运行时,运用反射机制动态创建而成,无需手动编写代码
JDK动态代理CGLIB动态代理(原理:是对指定的业务类生成一个子类,并覆盖其中的业务方法来实现代理)package net.cybclass.sp.service; /** * @author: wangxiaobo * @create: 2020-10-04 22:32 **/ public interface PayService { /** * 支付回调 * @param outTradeNo 订单号 * @return */ String callback(String outTradeNo); /** * 下单 * @param userId 用户id * @param productId 产品id * @return */ int save(int userId,int productId); }
package net.cybclass.sp.service; /** * @author: wangxiaobo * @create: 2020-10-04 22:33 **/ public class PayServiceImpl implements PayService { @Override public String callback(String outTradeNo) { System.out.println("目标类 PayServiceImpl 回调 方法 callback"); return outTradeNo; } @Override public int save(int userId, int productId) { System.out.println("目标类 PayServiceImpl 回调 方法 save"); return productId; } }
JDKProxy.java(jdk动态代理类)
import java.lang.reflect.Method; import java.lang.reflect.Proxy; /** * @author: wangxiaobo * @create: 2020-10-04 22:38 **/ public class JDKProxy implements InvocationHandler { //目标类 private Object targetObject; /** * 获取代理对象 * @param targetObject 目标类 * @return */ public Object newProxyInstance(Object targetObject) { this.targetObject = targetObject; //绑定关系,也就是和具体的那个实现类关联 return Proxy.newProxyInstance(targetObject.getClass().getClassLoader(), targetObject.getClass().getInterfaces(), this); } /** * JDK动态代理 * * @param proxy 静态代理对象 * @param method 要调用的方法 * @param args 方法调用时所需要参数 * @return * @throws Throwable */ @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { Object result = null; try { System.out.println("通过JDK动态代理调用"+method.getName()+",打印日志 begin"); result = method.invoke(targetObject, args); System.out.println("通过JDK动态代理调用"+method.getName()+",打印日志 end"); } catch (Exception ex) { ex.printStackTrace(); } return result; } }package net.cybclass.sp.test; import net.cybclass.sp.proxy.JDKProxy; import net.cybclass.sp.proxy.StaticProxyPayServiceImpl; import net.cybclass.sp.service.PayService; import net.cybclass.sp.service.PayServiceImpl; /** * @author: wangxiaobo * @create: 2020-10-04 22:48 **/ public class ProxyTest { public static void main(String[] args) { // PayService payService = new StaticProxyPayServiceImpl (new PayServiceImpl ()); // payService.save (234,567); JDKProxy jdkProxy = new JDKProxy (); PayService payService = (PayService) jdkProxy.newProxyInstance (new PayServiceImpl ()); payService.callback ("hello wrod"); } }
运行:
动态代理与静态代理相比较,最大的好处是接口中声明的所有方法都被转移到调用处理器一个集中的方法中处理,解耦和易维护。