文章目录
- 1. JDK 动态代理
- 2、CGLIB 动态代理
动态代理允许你在运行时创建代理对象,来代替原始对象执行某些操作。这在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();
}
}
输出结果为
检查权限...
添加用户
记录日志...
检查权限...
删除用户
记录日志...