什么是代理模式
代理模式主要对我们方法执行之前与之后实现增强
代理模式应用场景
- 日志的采集
- 权限控制
- 实现aop
- Mybatis mapper
- Spring的事务
- 全局捕获异常
- Rpc远程调用接口
- 代理数据源
代理模式实现的原理
代理模式主要包含三个角色,即抽象主题角色(Subject)、委托类角色(被代理角色,Proxied)以及代理类角色(Proxy),如上图所示:

抽象主题角色:可以是接口,也可以是抽象类;
委托类角色:真实主题角色,业务逻辑的具体执行者;
代理类角色:内部含有对真实对象RealSubject的引用,负责对真实主题角色的调用,并在真实主题角色处理前后做预处理和后处理。
代理模式创建方式
静态代理
静态代理需要自己人工编写代理类代码
基于接口实现方式
| public class OrderServiceProxy implements OrderService{ private OrderService orderService;
public OrderServiceProxy(OrderService orderService) { this.orderService = orderService; }
public String addOrder(String userName, String userPwd) { System.out.println("使用静态代理类打印日志开始:userName:" + userName + "," + userPwd); String result = orderService.addOrder(userName, userPwd); System.out.println("使用静态代理类打印日志结束:userName:" + userName + "," + userPwd); return result; } } public interface OrderService { /** * 需要被代理的方法 * @return */ String addOrder(String userName,String userPwd); } public class Test001 { public static void main(String[] args) { OrderService orderService = new OrderServiceProxy(new OrderServiceImpl()); orderService.addOrder("mayikt","123456"); } } |
基于继承的实现方式
| public class OrderServiceProxy extends OrderServiceImpl { private OrderService orderService;
public OrderServiceProxy(OrderService orderService) { this.orderService = orderService; }
public String addOrder(String userName, String userPwd) { System.out.println("使用静态代理类打印日志开始:userName:" + userName + "," + userPwd); String result = super.addOrder(userName, userPwd); System.out.println("使用静态代理类打印日志结束:userName:" + userName + "," + userPwd); return result; } } |
动态代理与静态代理的区别
动态代理不需要写代理类对象,通过程序自动生成,而静态代理需要我们自己写代理类对象。
动态代理
动态代理是在实现阶段不用关心代理类,而在运行阶段才指定哪一个对象。
动态代理类的源码是在程序运行期间由JVM根据反射等机制动态的生成 。
Jdk动态代理
JDK动态代理的一般步骤如下:
1.创建被代理的接口和类;
2.实现InvocationHandler接口,对目标接口中声明的所有方法进行统一处理;
3.调用Proxy的静态方法,创建代理类并生成相应的代理对象;
实现原理:利用拦截器机制必须实现InvocationHandler接口中的invoke方法实现对
我们的目标方法增强。
| public class JdkInvocationHandler implements InvocationHandler { /** * 目标对象 */ private Object target;
public JdkInvocationHandler(Object target) { this.target = target; }
/** * @param proxy 使用jdk程序生成的代理类 * @param method 目标方法 * @param args 方法需要传递的参数 * @return */ public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println("使用Jdk动态代理打印日志开始" + args[0]); Object result = method.invoke(target, args); System.out.println("使用Jdk动态代理打印日志结束" + args[1]); return result; }
public <T> T getProxy() { return (T) Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), this); }
} |
| JdkInvocationHandler jdkInvocationHandler = new JdkInvocationHandler(new OrderServiceImpl()); OrderServiceImpl orderService = jdkInvocationHandler.getProxy(); orderService.addOrder("mayikt", "meite"); |
加上该代码:
- 获取代理的生成的class文件
System.getProperties().put("sun.misc.ProxyGenerator.saveGeneratedFiles", "true")

CGLIB动态代理
利用asm字节码技术,生成子类实现对目标方法实现增强
实现方式
Maven依赖
| <dependencies> <dependency> <groupId>cglib</groupId> <artifactId>cglib</artifactId> <version>3.2.12</version> </dependency> </dependencies> |
核心代码
| public class CglibMethodInterceptor implements MethodInterceptor { public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable { System.out.println("<<<<<日志收集开始...>>>>>>>"); Object reuslt = proxy.invokeSuper(obj, args); System.out.println("<<<<<日志收集结束...>>>>>>>"); return reuslt; } } |
| System.setProperty(DebuggingClassWriter.DEBUG_LOCATION_PROPERTY, "D:\\code"); CglibMethodInterceptor cglibMethodInterceptor = new CglibMethodInterceptor(); Enhancer enhancer = new Enhancer(); // 设置代理类的付类 enhancer.setSuperclass(MemberServiceImpl.class); // 设置回调对象 enhancer.setCallback(cglibMethodInterceptor); // 创建代理对象 MemberServiceImpl orderServiceImpl = (MemberServiceImpl) enhancer.create(); orderServiceImpl.getMember(); |
Jdk与Cglib动态代理的区别
- Jdk动态代理利用反射技术生成匿名的代理类走InvokeHandler回调方法实现增强,同时也是一种基于接口的方式实现代理。
- Cglib动态代理利用asm字节码技术生成一个子类覆盖其中的方法实现增强,同时采用fastClass机制对整个代理类建立索引比反射效率要高
- 在Spring中如果需要被代理的对象如果实现了接口采用Jdk动态代理,没有实现接口则使用Cglib动态代理。