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

文章目录

    • 1. JDK 动态代理
    • 2、CGLIB 动态代理

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

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();
    }
}

输出结果为

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

你可能感兴趣的:(遇到的开发问题,编程基础,java,开发语言,代理模式)