Java动态代理实现案例
动态代理是Java中非常重要的设计模式,允许在运行时动态创建代理对象,主要有两种实现方式:

JDK动态代理(基于接口)
适用场景:目标类实现了接口
// 1. 定义接口
public interface UserService {
void addUser(String name);
void deleteUser(int id);
String findUser(int id);
}
// 2. 实现类
public class UserServiceImpl implements UserService {
@Override
public void addUser(String name) {
System.out.println("添加用户:" + name);
}
@Override
public void deleteUser(int id) {
System.out.println("删除用户ID:" + id);
}
@Override
public String findUser(int id) {
System.out.println("查询用户ID:" + id);
return "用户" + id;
}
}
// 3. 实现InvocationHandler
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
public class LogInvocationHandler implements InvocationHandler {
private Object target; // 目标对象
public LogInvocationHandler(Object target) {
this.target = target;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
// 前置增强
System.out.println("[日志] 开始执行方法:" + method.getName());
// 调用目标方法
Object result = method.invoke(target, args);
// 后置增强
System.out.println("[日志] 方法执行完成:" + method.getName());
return result;
}
}
// 4. 使用动态代理
public class JDKProxyDemo {
public static void main(String[] args) {
// 创建目标对象
UserService target = new UserServiceImpl();
// 创建代理对象
UserService proxy = (UserService) Proxy.newProxyInstance(
target.getClass().getClassLoader(), // 类加载器
target.getClass().getInterfaces(), // 接口数组
new LogInvocationHandler(target) // 调用处理器
);
// 使用代理对象
proxy.addUser("张三");
proxy.deleteUser(1);
String user = proxy.findUser(100);
System.out.println("查询结果:" + user);
}
}
CGLIB动态代理(基于继承)
适用场景:目标类没有实现接口,或需要对类进行代理
// 1. 添加依赖(Maven)
<dependency>
<groupId>cglib</groupId>
<artifactId>cglib</artifactId>
<version>3.3.0</version>
</dependency>
// 2. 目标类(无需接口)
public class UserDao {
public void addUser(String name) {
System.out.println("添加用户:" + name);
}
public final void deleteUser(int id) {
System.out.println("删除用户ID:" + id);
}
}
// 3. 实现MethodInterceptor
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
import java.lang.reflect.Method;
public class CglibProxyInterceptor implements MethodInterceptor {
private Object target;
public CglibProxyInterceptor(Object target) {
this.target = target;
}
// 创建代理对象
public Object getProxy() {
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(target.getClass());
enhancer.setCallback(this);
return enhancer.create();
}
@Override
public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
System.out.println("[CGLIB] 前置处理");
// 调用目标方法
Object result = method.invoke(target, args);
System.out.println("[CGLIB] 后置处理");
return result;
}
}
// 4. 使用CGLIB代理
public class CglibProxyDemo {
public static void main(String[] args) {
// 创建目标对象
UserDao target = new UserDao();
// 创建代理
CglibProxyInterceptor interceptor = new CglibProxyInterceptor(target);
UserDao proxy = (UserDao) interceptor.getProxy();
// 使用代理对象
proxy.addUser("李四");
// proxy.deleteUser(2); // 注意:final方法无法被代理
}
}
通用动态代理工具类
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
/**
* 通用动态代理工具类
*/
public class DynamicProxyUtil {
/**
* JDK动态代理
*/
@SuppressWarnings("unchecked")
public static <T> T createJDKProxy(T target, ProxyHandler handler) {
return (T) Proxy.newProxyInstance(
target.getClass().getClassLoader(),
target.getClass().getInterfaces(),
new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
handler.before(method, args);
Object result = method.invoke(target, args);
handler.after(method, result);
return result;
}
}
);
}
/**
* 代理处理器接口
*/
public interface ProxyHandler {
default void before(Method method, Object[] args) {}
default void after(Method method, Object result) {}
}
}
// 使用示例
public class MainDemo {
public static void main(String[] args) {
// 创建目标对象
UserService userService = new UserServiceImpl();
// 创建代理
UserService proxy = DynamicProxyUtil.createJDKProxy(userService,
new DynamicProxyUtil.ProxyHandler() {
@Override
public void before(Method method, Object[] args) {
System.out.println("通用前置处理");
}
@Override
public void after(Method method, Object result) {
System.out.println("通用后置处理");
}
}
);
// 测试
proxy.addUser("测试用户");
}
}
实际应用场景示例:事务管理
// 事务注解
import java.lang.annotation.*;
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Transactional {
}
// 事务代理实现
public class TransactionProxy {
@SuppressWarnings("unchecked")
public static <T> T createTransactionProxy(T target) {
return (T) Proxy.newProxyInstance(
target.getClass().getClassLoader(),
target.getClass().getInterfaces(),
(proxy, method, args) -> {
Transactional transactional = method.getAnnotation(Transactional.class);
if (transactional != null) {
System.out.println("开启事务...");
try {
Object result = method.invoke(target, args);
System.out.println("提交事务...");
return result;
} catch (Exception e) {
System.out.println("回滚事务...");
throw e;
}
} else {
return method.invoke(target, args);
}
}
);
}
}
// 使用
public class BusinessService {
@Transactional
public void doBusiness() {
System.out.println("执行业务逻辑");
}
public void normalOperation() {
System.out.println("普通操作,无需事务");
}
}
| 特性 | JDK动态代理 | CGLIB动态代理 |
|---|---|---|
| 实现方式 | 基于接口 | 基于继承(生成子类) |
| 性能 | 较低(反射调用) | 较高(直接调用) |
| 限制 | 必须有接口 | final方法不能被代理 |
| 适用版本 | JDK 1.3+ | 需要引入cglib库 |
选择建议:
- 如果目标类有接口 → 优先使用JDK动态代理
- 如果没有接口或需要代理类本身 → 使用CGLIB
- Spring框架默认使用JDK动态代理,没有接口时自动切换CGLIB