Java 动态代理实现方式详解及案例

动态代理是一种强大的设计模式,它允许我们在不修改目标对象的情况下,为其添加额外的功能。在 Java 中,实现动态代理主要有三种方式:JDK 动态代理、CGLIB 动态代理和 ByteBuddy 动态代理。

1. JDK 动态代理

JDK 动态代理是基于接口实现的,需要目标对象实现一个或多个接口。

// 创建接口
public interface UserDao {
    void save();
}

// 创建目标对象
public class UserDaoImpl implements UserDao {
    @Override
    public void save() {
        System.out.println('保存用户信息');
    }
}

// 创建代理对象的实现类
public class UserDaoProxy implements InvocationHandler {
    private Object target;

    public Object bind(Object target) {
        this.target = target;
        return Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), this);
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println('开启事务');
        Object result = method.invoke(target, args);
        System.out.println('提交事务');
        return result;
    }
}

// 测试
public class Test {
    public static void main(String[] args) {
        UserDao userDao = new UserDaoImpl();
        UserDao proxy = (UserDao) new UserDaoProxy().bind(userDao);
        proxy.save();
    }
}

2. CGLIB 动态代理

CGLIB 动态代理是基于子类实现的,不需要目标对象实现接口。它通过继承目标类并重写方法来实现代理。

// 创建目标对象
public class UserDao {
    public void save() {
        System.out.println('保存用户信息');
    }
}

// 创建代理对象的实现类
public class UserDaoProxy implements MethodInterceptor {
    private Object target;

    public Object bind(Object target) {
        this.target = target;
        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('开启事务');
        Object result = proxy.invokeSuper(obj, args);
        System.out.println('提交事务');
        return result;
    }
}

// 测试
public class Test {
    public static void main(String[] args) {
        UserDao userDao = new UserDao();
        UserDao proxy = (UserDao) new UserDaoProxy().bind(userDao);
        proxy.save();
    }
}

3. ByteBuddy 动态代理

ByteBuddy 动态代理是一种基于字节码操作的代理方式,它能够在运行时动态生成代理类的字节码。

// 创建目标对象
public class UserDao {
    public void save() {
        System.out.println('保存用户信息');
    }
}

// 创建代理对象的实现类
public class UserDaoProxy {
    public static void main(String[] args) throws IllegalAccessException, InstantiationException {
        Class<? extends UserDao> dynamicType = new ByteBuddy()
                .subclass(UserDao.class)
                .method(named('save'))
                .intercept(MethodDelegation.to(UserDaoInterceptor.class))
                .make()
                .load(UserDao.class.getClassLoader())
                .getLoaded();

        UserDao userDao = dynamicType.newInstance();
        userDao.save();
    }
}

// 创建拦截器
public class UserDaoInterceptor {
    public static void save() {
        System.out.println('开启事务');
        System.out.println('保存用户信息');
        System.out.println('提交事务');
    }
}

注意: 以上代码为示例代码,并非完整可运行代码。实际使用时,需要根据具体情况进行相应的调整和完善。

总结

本文介绍了 Java 动态代理的三种常用实现方式,并提供每个方式的代码案例。您可以根据自己的需求选择合适的方式来实现动态代理。

动态代理在 AOP(面向切面编程)、事务管理、权限控制等方面都有着广泛的应用。掌握动态代理技术,能够帮助您更好地理解和使用 Java 语言。


原文地址: https://www.cveoy.top/t/topic/yvt 著作权归作者所有。请勿转载和采集!

免费AI点我,无需注册和登录