代理
1. 静态代理
静态代理是 Java 中一种常见的代理模式实现方式,属于结构型设计模式。它的核心思想是:为一个对象提供一个代理对象,并由代理对象控制对原对象的访问。下面使用代码来展示一下静态代理对一个实现类进行代理增强。
接口:
1 2 3
| public interface UserService{ void show(); }
|
实现类:
1 2 3 4 5 6
| public class UserServiceImpl implements UserService{ @Override public void show() { System.out.println("我要看电视了"); } }
|
代理类:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| public class UserPoxy implements UserService{
private UserService userService;
public UserPoxy(UserService userService) { this.userService = userService; }
@Override public void show() { System.out.println("代理增强:先打开电视"); userService.show(); System.out.println("代理增强:关闭电视"); } }
|
测试类:
1 2 3 4 5 6 7 8
| public class App { public static void main( String[] args ) { UserService userService = new UserServiceImpl(); UserPoxy userPoxy = new UserPoxy(userService); userPoxy.show(); } }
|
输出:
1 2 3 4 5 6
| 代理增强:先打开电视 我要看电视了 代理增强:关闭电视
进程已结束,退出代码为 0
|
虽然这种方式可以对实现类进行代理增强,但是代码的复用性不高,同时比如需要100个代理类,就需要写100个。这样不好,下面进行介绍动态代理,可以完美的解决这个问题。
2. 动态代理
现在使用最多的就是JDK动态代理和CGLIB动态代理。
- JDK动态代理:这个是对接口进行的代理模式,由JDK内部提供,通过
java.lang.reflect.Proxy 类和 InvocationHandler 接口实现。当代理的类调用方法时进行拦截代理。
- CGLIB 动态代理:这个是由外部方式引入,比JDK动态代理更加强大(可以直接代理没有接口的类)。
1. JDK动态代理演示
接口:
1 2 3
| public interface UserService{ void show(); }
|
实现类:
1 2 3 4 5 6
| public class UserServiceImpl implements UserService { @Override public void show() { System.out.println("我要看电视了"); } }
|
代理拦截器:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| public class UserProxyHandler implements InvocationHandler {
private Object target;
public UserProxyHandler(Object target) { this.target = target; }
@Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("JDK动态代理:先打开电视"); Object object = method.invoke(target, args); System.out.println("JDK动态代理:关闭电视"); return object; } }
|
测试类:
1 2 3 4 5 6 7 8 9 10
| public class test { public static void main(String[] args) { UserService userService = new UserServiceImpl(); UserService proxy = (UserService)Proxy.newProxyInstance(userService.getClass().getClassLoader(), userService.getClass().getInterfaces(), new UserProxyHandler(userService)); proxy.show(); } }
|
输出:
1 2 3 4 5
| JDK动态代理:先打开电视 我要看电视了 JDK动态代理:关闭电视
进程已结束,退出代码为 0
|
JDK底层实现原理:Proxy.newProxyInstance()会在运行时通过字节码技术(如 ASM 或内部的sun.misc.ProxyGenerator)动态生成一个$Proxy0类(名字可能不同),该类:
- 继承
java.lang.reflect.Proxy
- 实现了传入的所有接口
- 接口中每个方法的实现都会调用
InvocationHandler.invoke()
JDK 动态代理是一种轻量级、无需额外依赖的代理方式,适用于基于接口编程的场景。它的核心思想是:将方法调用统一拦截到 InvocationHandler.invoke() 中进行增强处理,从而实现如日志、事务、权限控制等 AOP 功能。
2. CGLIB动态代理演示
首先先引入CGLIB的依赖:
1 2 3 4 5
| <dependency> <groupId>cglib</groupId> <artifactId>cglib</artifactId> <version>3.3.0</version> </dependency>
|
编写需要代理的类:
1 2 3 4 5
| public class UserServiceImpl { public void show() { System.out.println("我要看电视了"); } }
|
测试类:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| public class test { public static void main(String[] args) { Enhancer enhancer = new Enhancer(); enhancer.setSuperclass(UserServiceImpl.class); enhancer.setCallback(new UserProxyInterceptor()); UserServiceImpl userService = (UserServiceImpl) enhancer.create();
userService.show(); } }
|
代理拦截器:
1 2 3 4 5 6 7 8 9
| public class UserProxyInterceptor implements MethodInterceptor { @Override public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable { System.out.println("CGLIB代理:先打开电视"); Object object = methodProxy.invokeSuper(o, objects); System.out.println("CGLIB代理:关闭电视"); return object; } }
|
注意:需要在VM中这样配置,不然会报错!!!!
1 2
| --add-opens java.base/java.lang=ALL-UNNAMED --add-opens java.base/sun.net.util=ALL-UNNAMED
|

输出:
1 2 3 4 5 6
| CGLIB代理:先打开电视 我要看电视了 CGLIB代理:关闭电视
进程已结束,退出代码为 0
|
调用过程:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| main() │ ▼ enhancer.create() → 动态生成 UserService$$EnhancerByCGLIB │ ▼ proxy.saveUser("张三") │ ▼ UserService$$EnhancerByCGLIB.saveUser() │ ▼ MyInterceptor.intercept(...) │ ▼ proxy.invokeSuper() → 调用 UserService.saveUser()(原始方法) │ ▼ 返回结果
|