JAVA代理

java代理静态代理和动态代理

简介 优点 缺点
静态代理 在不修改目标对象的基础上,通过扩展类对目标对象进行增强和扩展。 静态代理对客户(测试类)隐藏了被代理类接口(目标类接口)的具体实现类,在一定程度上实现了解耦合,同时提高了安全性。 静态代理类需要实现目标类(被代理类)的接口,并实现其方法,造成了代码的大量冗余。静态代理只能对某个固定接口的实现类进行代理服务,其灵活性不强。故一般大项目不会选择静态代理。
jdk动态代理 使用java反射包中的类和接口实现动态代理的功能 动态代理实现了只需要将被代理对象作为参数传入代理类就可以获取代理类对象,从而实现类代理,具有较强的灵活性。动态代理的服务内容不需要像静态代理一样写在每个代码块中,只需要写在invoke()方法中即可,降低了代码的冗余度。Java动态代理使用Java原生的反射API进行操作,在生成类上比较高效 只能为接口创建代理
cglib代理 cglib是一个强大、高性能的字节码生成库,它用于在运行时扩展Java类和实现接口;本质上它是通过动态的生成一个子类去覆盖所要代理的类(非final修饰的类和方法)。 CGLIB使用ASM框架直接对字节码进行操作,在类的执行过程中比较高效,可以对非接口类进行代理

例子

  • 测试类
public class Test {
    public static void main(String[] args) {
        UserServiceImpl userServiceImpl = new UserServiceImpl();
        // 基于jdk的动态代理(代理类需要实现接口)
        UserService userService = JdkProxy.getProxyInstance(userServiceImpl, MyAspect.class);
        System.out.println("jdk代理:" + userService.userOrderQuery(null));

        // 基于spring的cglib动态代理
        UserService userService2 = CglibProxy.getProxyInstance(userServiceImpl, MyAspect.class);
        System.out.println("cglib代理:" + userService2.userOrderQuery(null));
    }
}
  • 增强类
点击查看代码
public class MyAspect implements Aspect {
    private final TimeInterval interval = new TimeInterval();
    @Override
    public boolean before(Object o, Method method, Object[] objects) {
        System.out.println(String.format("className:[%s],methodName:[%s]", o.getClass().getName(),method.getName()));
        return true;
    }

    @Override
    public boolean after(Object o, Method method, Object[] objects, Object o1) {
        System.out.println(String.format("耗时:[%s],返回结果:%s", this.interval.intervalMs(), o1));
        return true;
    }

    @Override
    public boolean afterException(Object o, Method method, Object[] objects, Throwable throwable) {
        return false;
    }
}
  • jdk动态代理
点击查看代码
public class JdkProxy {
    /**
     * @describe
     * @param target 被代理类的对象
     * @param aspectClass 需要执行的切面类
     * @return T
     * @modify
     */
    public static <T> T getProxyInstance(T target, Class aspectClass) {
        // 需要执行的切面对象
//        Aspect aspect = (Aspect) ReflectUtil.newInstance(aspectClass, new Object[0]);
        Aspect aspect = null;
        try {
            aspect = (Aspect) aspectClass.newInstance();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
        Aspect finalAspect = aspect;
        InvocationHandler invocationHandler = (proxy, method, args) -> {
            // 原方法执行前的额外任务
            finalAspect.before(target, method, args);
            // obj:被代理类的对象
            Object result = method.invoke(target, args);
            // 执行完原方法后可执行额外的任务
            finalAspect.after(target, method, args, result);
            return result;
        };
        // 第二个参数的意思:因为被代理类和代理类要实现同样的接口
        return (T)Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), invocationHandler);
    }
  • cglib动态代理
点击查看代码
public class CglibProxy {
    /**
     * @describe
     * @param target 被代理类的对象
     * @param aspectClass 需要执行的切面类
     * @return T
     * @modify
     */
    public static <T> T getProxyInstance(T target, Class aspectClass) {
        Aspect aspect = null;
        try {
            aspect = (Aspect) aspectClass.newInstance();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
        Aspect finalAspect = aspect;
        MethodInterceptor methodInterceptor = (o, method, objects, methodProxy) -> {
            // 原方法执行前的额外任务
            finalAspect.before(target, method, objects);
            // target:被代理类的对象
//            Object result = methodProxy.invoke(target, objects);
//            Object result = methodProxy.invokeSuper(o, objects);
            Object result = method.invoke(target, objects);
            // 执行完原方法后可执行额外的任务
            finalAspect.after(target, method, objects, result);
            return result;
        };
        Enhancer enhancer = new Enhancer();
        enhancer.setSuperclass(target.getClass());
        enhancer.setCallback(methodInterceptor);
        return (T)enhancer.create();
    }
}
  • 输出

className:[com.crazy.practice.boot.service.impl.UserServiceImpl],methodName:[userOrderQuery]
耗时:[59],返回结果:[UserOrder(averageUser=AverageUser(userSeq=100, userId=120001, userName=王丽丽, userMobilePhone=null, userState=null, createTime=null), orderJnlNo=null, userSeq=1, orderState=null, goodsId=1001, goodsName=水杯, createTime=null)]
jdk代理:[UserOrder(averageUser=AverageUser(userSeq=100, userId=120001, userName=王丽丽, userMobilePhone=null, userState=null, createTime=null), orderJnlNo=null, userSeq=1, orderState=null, goodsId=1001, goodsName=水杯, createTime=null)]

className:[com.crazy.practice.boot.service.impl.UserServiceImpl],methodName:[userOrderQuery]
耗时:[91],返回结果:[UserOrder(averageUser=AverageUser(userSeq=100, userId=120001, userName=王丽丽, userMobilePhone=null, userState=null, createTime=null), orderJnlNo=null, userSeq=1, orderState=null, goodsId=1001, goodsName=水杯, createTime=null)]
cglib代理:[UserOrder(averageUser=AverageUser(userSeq=100, userId=120001, userName=王丽丽, userMobilePhone=null, userState=null, createTime=null), orderJnlNo=null, userSeq=1, orderState=null, goodsId=1001, goodsName=水杯, createTime=null)]

posted @ 2023-05-24 11:31  土豆泥呀  阅读(48)  评论(0)    收藏  举报