【代码】Java中的动态代理实战


动态代理允许你在运行时创建代理对象,来代替原始对象执行某些操作。这在AOP(面向切面编程)中非常有用,用于实现日志记录、性能监控、事务管理等功能。
Java提供了两种主要的动态代理实现方法:基于接口的代理(JDK 动态代理)和基于类的代理(CGLIB)。
在这里插入图片描述

1. JDK 动态代理

JDK动态代理要求目标对象实现一个或多个接口,代理对象会实现这些接口并将方法调用转发给实际的目标对象。
首先,定义一个接口:

public interface UserDao {
    void addUser();
    void deleteUser();
}

然后,创建一个实现了该接口的目标类:

public class UserDaoImpl implements UserDao{
    @Override
    public void addUser() {
        System.out.println("添加用户");
    }

    @Override
    public void deleteUser() {
        System.out.println("删除用户");
    }
}

再然后,添加一个切面,比如检查权限,记录日志等

public class MyAspect {
    public void checkPermissions(){
        System.out.println("检查权限...");
    }

    public void log(){
        System.out.println("记录日志...");
    }
}


接下来,创建一个实现了InvocationHandler接口的类,它将处理代理方法的调用:

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

public class JDKProxy implements InvocationHandler {

    private UserDao userDao;
    public Object createProxy(UserDao userDao){
        this.userDao = userDao;
        // 类加载器
        ClassLoader classLoader = JDKProxy.class.getClassLoader();
        // 被代理对象实现的所有接口
        Class[] clazz = userDao.getClass().getInterfaces();
        // 使用代理类进行增强,返回的是代理后的对象
        return Proxy.newProxyInstance(classLoader,clazz,this);
    }

    /**
     * 所有动态代理类的方法调用,都会交由invoke方法处理
     * @return
     * @throws Throwable
     */
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        // 声明切面
        MyAspect myAspect = new MyAspect();
        // 前增强
        myAspect.checkPermissions();
        // 在目标类上调用方法,并传入参数
        Object obj = method.invoke(userDao, args);
        // 后增强
        myAspect.log();
        return obj;
    }
}

最后,使用Proxy类创建代理对象:

public class JDKProxyTest {
    public static void main(String[] args) {
        // 创建代理对象
        JDKProxy jdkProxy = new JDKProxy();
        // 创建目标对象
        UserDao userDao = new UserDaoImpl();

        // 从代理对象中获取增强后的目标对象
        UserDao userDao1 = (UserDao) jdkProxy.createProxy(userDao);
        // 执行方法
        userDao1.addUser();;
        userDao1.deleteUser();
    }
}

输出将会是

检查权限...
添加用户
记录日志...
检查权限...
删除用户
记录日志...

2、CGLIB 动态代理

CGLIB动态代理允许在不修改目标类源代码的情况下创建代理。它通过生成目标类的子类来实现代理。

首先,定义一个目标类

public class UserDaoV2 {
    public void addUser() {
        System.out.println("添加用户");
    }

    public void deleteUser() {
        System.out.println("删除用户");
    }
}

然后,创建切面

public class MyAspect {
    public void checkPermissions(){
        System.out.println("检查权限...");
    }

    public void log(){
        System.out.println("记录日志...");
    }
}

创建 InvocationHandler:这是一个实现了 InvocationHandler 接口的类,用于拦截方法调用并执行自定义逻辑(切面)。

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 CglibProxy implements MethodInterceptor {
    public Object createProxy(Object target){
        // 创建动态类对象
        Enhancer enhancer = new Enhancer();
        // 确定需要增强的类,设置其父类
        enhancer.setSuperclass(target.getClass());
        // 添加回调方法
        enhancer.setCallback(this);
        // 返回创建的代理类
        return enhancer.create();
    }

    @Override
    public Object intercept(Object proxy, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
        // 声明切面
        MyAspect myAspect = new MyAspect();
        // 前增强
        myAspect.checkPermissions();
        // 在目标类上调用方法,并传入参数
        Object obj = methodProxy.invokeSuper(proxy,objects);
        // 后增强
        myAspect.log();
        return obj;
    }
}

最后,使用

import cn.diyai.proxy.dynamic_proxyV2.dao.UserDaoV2;

public class CglibProxyTest {
    public static void main(String[] args) {
        // 创建代理对象
        CglibProxy cglibProxy = new CglibProxy();

        // 创建目标对象
        UserDaoV2 userDao = new UserDaoV2();

        // 获取增强后的目标对象
        UserDaoV2 userDao1 = (UserDaoV2) cglibProxy.createProxy(userDao);
        // 执行方法
        userDao1.addUser();
        userDao1.deleteUser();
    }
}

输出结果为

检查权限...
添加用户
记录日志...
检查权限...
删除用户
记录日志...
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值