Spring中的动态代理(两种)

代理机制

采用代理模式 主要为了解耦 将公共的通用方法放到代理对象中
业务层 专注于业务代码

代理的特点:
1. 为什么使用代理 ? 因为不方便
2. 代理的作用 代理要解决(扩展)某些实际的问题
3. 用户最终执行目标方法

就是为了解耦 灵活的代理代码

JDK模式

  1. JDK代理模式是Java原生提供的API
  2. JDK代理要求: 被代理者必须 要么是 接口 , 要么是 实现类
  3. 灵活: 代理对象应该开起来和被代理者一模一样(里面的方法相同)

使用JDK创建动态代理

public class JDKProxy {
    //提供获取动态代理的方法
    //返回动态代理的方法
    public static Object getProxy(Object target){// 传入 目标对象
        //获取类加载器
        ClassLoader classLoader = target.getClass().getClassLoader();
        //获取接口数组类型
        Class<?>[] interfaces = target.getClass().getInterfaces();
        //代理对象指定方法时的回调方法 代理对象调用方法时执行 InvocationHandler

        return Proxy.newProxyInstance(classLoader,interfaces,invoke(target));
    }
    //构建InvocationHandler的方法  传入目标对象
    public static InvocationHandler invoke(Object target){//返回一个 InvocationHandler
        return new InvocationHandler() {// 是接口 需要实现里面的方法
            @Override
            //Object proxy 代理对象, Method method 目标方法, Object[] args 参数数组
            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 static Object getProxy(Object target){
    ClassLoader classLoader = target.getClass().getClassLoader();

    Class<?>[] interfaces = target.getClass().getInterfaces();

    return Proxy.newProxyInstance(classLoader, interfaces, new InvocationHandler() {
        @Override
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            System.out.println("开启事务");
            //调用方法
            Object invoke = method.invoke(target, args);
            //提交事务
            System.out.println("事务提交");
            //返回 方法
            return invoke;
        }
    });
}

CGLib 代理模式

jdk代理 必须 有实现 接口 没有接口不能运行

cgblib代理 要求被代理者有没有接口都可以
代理对象必须是目标对象的 子类

public class CGLibProxy {
    public static Object getProxy(Object target){
        //创建增强器
        Enhancer enhancer = new Enhancer();
        //代理对象时 目标对象的 子集
        //设定 父级:目标对象
        enhancer.setSuperclass(target.getClass());
        //定义回调方法 代理对象执行目标方法调用
        enhancer.setCallback(getMethodInterceptor(target));
        //创建代理对象  并返回
        return enhancer.create();
    }
    public static MethodInterceptor getMethodInterceptor(Object target){
        return new MethodInterceptor() {
            @Override // Object o 代理对象, Method method 目标方法, Object[] objects 参数数组 , methodProxy 代理的方法 
            public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
                System.out.println("开始事务CGlib");
                //执行 目标 方法
                Object result = method.invoke(target, objects);
                System.out.println("事务提交CGlib");
                //返回 方法
                return result;
            }
        };
    }
}

另一种写法

public static Object getProxy2(Object target){
    //创建增强器
    Enhancer enhancer = new Enhancer();
    //设定 父级
    enhancer.setSuperclass(target.getClass());
    //定义回调
    enhancer.setCallback(new MethodInterceptor() {
        @Override// Object o 代理对象, Method method 目标方法, Object[] objects 参数数组 , methodProxy 代理的方法 
        public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
            System.out.println("开始事务CGlib");
            //执行方法
            Object result = method.invoke(target, objects);
            System.out.println("事务提交CGlib");
            //返回 方法
            return result;
        }
    });
    return enhancer.create();
}

两种模式的使用

JDK

ApplicationContext context = new AnnotationConfigApplicationContext(SpringConfig.class);//Spring对象管理容器

UserService service = context.getBean(UserService.class);//获取接口类

UserService proxy = (UserService)JDKProxy.getProxy(service);//代理执行

proxy.addUser();//执行方法

CGLib

ApplicationContext context = new AnnotationConfigApplicationContext(SpringConfig.class);//Spring对象管理容器

UserService service = context.getBean(UserServiceImpl.class);//获取接口类

UserService proxy = (UserService) CGLibProxy.getProxy(service);//代理执行

proxy.addUser();//执行方法
上一篇:Spring Bean的生命周期(一图看懂bean生命周期)


下一篇:人工智能研究中心快递柜——代码分析九