zl程序教程

您现在的位置是:首页 >  后端

当前栏目

Spring 初识Aop JDK动态代理实现 原理初显

SpringJDK代理AOP原理 实现 动态 初识
2023-06-13 09:14:16 时间

Spring 初识Aop JDK动态代理实现 原理初显

一、项目结构

二、具体步骤:

1、创建maven项目 创建好包结构

2、写一个TestDao接口 及实现类

/**
 * @version 1.0
 * @author: crush
 * @date: 2021-03-05 10:26
 */
public interface TestDao {
    public void sayHello();
    public void save();
    public void modify();
    public void delete();
}

TestDaoImpl

/**
 * @version 1.0
 * @author: crush
 * @date: 2021-03-05 10:27
 */
@Repository
public class TestDaoImpl implements TestDao {
    public void sayHello() {
        System.out.println("武汉加油!中国加油!");
    }
    public void save() {
        System.out.println("保存");

    }
    public void modify() {
        System.out.println("修改");
    }

    public void delete() {
        System.out.println("删除");
    }
}

3、 写一个自己的切面类

/**
 * @version 1.0
 * @author: crush
 * @date: 2021-03-10 11:41
 */
public class MyAspect {
    public void check(){
        System.out.println("模拟权限处理");
    }
    public void except(){
        System.out.println("模拟异常处理");
    }
    public void log(){
        System.out.println("模拟日志记录");
    }
    public void monitor(){
        System.out.println("性能检测");
    }
}

4、java JDK 实现动态代理

/**
 * @version 1.0
 * @author: crush
 * @date: 2021-03-10 11:47
 *
 * InvocationHandler是由代理实例的调用处理程序实现的接口。
 * 每个代理实例都有一个关联的调用处理程序。
 * 在代理实例上调用方法时,该方法调用将被编码并分派到其调用处理程序的invoke方法
 */
public class JdkDynamicProxy implements InvocationHandler {

    private Object object;

    /**
     * @Date 16:24 2021/3/10
     *
     * 创建代理的方法 建立代理对象和真实对象的代理关系 并返回代理对象
     **/
    public Object createProxy(Object object){
        this.object=object;
        // 1、 类加载器
        ClassLoader classLoader = JdkDynamicProxy.class.getClassLoader();

        // 2、 被代理对象 实现的所有接口
        Class[] interfaces = object.getClass().getInterfaces();

        // 3、 使用代理类进行增强 返回代理后的对象

        /**
         *     利用Java的反射技术(Java Reflection),
         *     在运行时创建一个实现某些给定接口的新类(也称“动态代理类”)及其实例(对象),
         *     代理的是接口(Interfaces),不是类(Class),也不是抽象类。
         *     在运行时才知道具体的实现,spring aop就是此原理
         */
        return Proxy.newProxyInstance(classLoader,interfaces,this);
        /**
         * newProxyInstance,方法有三个参数:
         *
         * loader: 用哪个类加载器去加载代理对象
         *
         * interfaces:动态代理类需要实现的接口
         *
         * h:动态代理方法在执行时,会调用h里面的invoke方法去执行
         */
    }
    /**
     * @Param [proxy 是被代理的对象,
     *         method 是将要被执行的方法,
     *         args 是执行方法 时需要的参数]
     * @return java.lang.Object
     *
     * 处理代理实例上的方法调用并返回结果。在与之关联的代理实例上调用方法时,将在调用处理程序上调用该方法。
     *
     * invoke 三个参数
     * proxy:就是代理对象,newProxyInstance方法的返回对象
     *
     * method:调用的方法
     *
     * args: 方法中的参数
     **/
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {

        MyAspect myAspect = new MyAspect();
        myAspect.check();
        myAspect.except();
        // 在目标类上调用方法并传入参数 相当于调用testDao中的方法
        Object obj = method.invoke(object, args);
        myAspect.log();
        myAspect.monitor();
        return obj;
    }
}

5、JDK 动态代理测试

    @Test
    public void JdkDynamicTest(){
        //创建代理对象
        JdkDynamicProxy proxy = new JdkDynamicProxy();

        //创建目标对象
        TestDao testDao = new TestDaoImpl();
        /**
         *  从代理对象中获取到增强后的目标对象,
         *  该对象是一个被代理的对象
         *  它会进入到代理的逻辑方法 invoke 中
         */
        TestDao  testAdvice = (TestDao) proxy.createProxy(testDao);
        // 执行方法
        testAdvice.sayHello();
    }

6、Cglib 实现动态代理

/**
 * @version 1.0
 * @author: crush
 * @date: 2021-03-10 16:23
 */
public class CglibDynamicProxy implements MethodInterceptor {

    /**
     * @Param [o, method, objects, methodProxy]
     * 创建代理的方法 生成CGLIB代理对象
     * target 是目标对象 需要增强的对象
     * 返回目标对象的CGLIB 代理对象
     **/
    public Object creatProxy(Object target){
        // 创建一个动态类对象 即增强类对象
        Enhancer enhancer = new Enhancer();
        // 确定需要增强的类 设置其父类
        //超类 – 要扩展的类或要实现的接口
        enhancer.setSuperclass(target.getClass());

        // 确定代理逻辑对象为当前对象
        // 要求当前对象实现MethodInterceptor 的方法
        enhancer.setCallback(this);

        // 返回创建的代理对象
        return enhancer.create();
    }
    /**
     * @Param [o, method, objects, methodProxy]
     * intercept 方法慧再程序执行目标方法时被调用
     * proxy 是CGLIB 根据指定父类生成的代理对象
     * method 是拦截方法
     * args 是拦截方法的参数数组
     * methodProxy 是方法代理对象 拥有执行父类的方法  返回代理结果
     **/
    @Override
    public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
        MyAspect myAspect = new MyAspect();
        myAspect.check();
        myAspect.except();
        // 在目标类上调用方法并传入参数 相当于调用testDao中的方法
        Object obj = methodProxy.invokeSuper(proxy, args);
        myAspect.log();
        myAspect.monitor();
        return obj;
    }
}

7、Cglib 测试

    @Test
    public void CglibDynamicProxyTest(){
        // 创建代理对象
        CglibDynamicProxy proxy = new CglibDynamicProxy();
        // 创建目标对象
        TestDao testDao = new TestDaoImpl();
        //获取增强后的目标对象
        TestDao testAdvice  = (TestDao) proxy.creatProxy(testDao);
        //执行方法
        testAdvice.save();
    }

三、自言自语

又到一天中课间休息时间拉。