Java练习:Proxy切面编程

本文通过JDK动态代理展示了如何利用Proxy在运行时生成代理类,代理订单业务接口,实现在方法执行前后插入时间检测的切面功能。示例中创建了订单业务接口及其实现,然后通过Aspect接口的getProxy方法动态生成代理类,结合TimeUsageAspect切面实现类记录方法执行时间。测试用例验证了代理功能的正确性。
摘要由CSDN通过智能技术生成

目标:利用Proxy完成一个订单业务时间检测

知识点:

Proxy

  1. JDK动态代理:java.lang.reflect.Proxy。
  2. 动态生成代理类:在程序运行时生成代理类来进行代理,主要利用Java的反射机制。
  3. Proxy代理的是接口,并不是类或抽象类。
使用:

业务代码:

package com.miracle.study.aspect;

/**
 * 订单业务接口
 * @author Miracle
 * @date 2021/4/4 12:52
 */
public interface IOrder {

    /**
     * 订单支付
     * @throws InterruptedException
     */
    void pay() throws InterruptedException;

    /**
     * 订单状态展示
     */
    void show();
}
package com.miracle.study.aspect;

/**
 * 订单业务接口实现
 * @author Miracle
 * @date 2021/4/4 12:53
 */
public class Order implements IOrder{

    int state = 0;

    @Override
    public void pay() throws InterruptedException {
        // 模拟业务进行
        Thread.sleep(50);
        this.state = 1;
    }

    @Override
    public void show() {

        System.out.println("order status:" + this.state);
    }
}

Proxy切面接口:

package com.miracle.study.aspect;


import java.lang.reflect.InvocationHandler;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.Arrays;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * 代理接口
 * @author Miracle
 * @date 2021/4/4 12:50
 */
public interface Aspect {

    /**
     * 方法执行前
     */
    void before();

    /**
     * 方法执行后
     */
    void after();

    /**
     * 代理类生成
     * @param cls 需要代理的类
     * @param aspects 所有切面实现类
     * @param <T>
     * @return
     */
    static <T> T getProxy(Class<T> cls, String ... aspects) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {

        var aspectInsts = Arrays.stream(aspects).map(name ->  {
            try {
                Class<?> clazz = Class.forName(name);
                return (Aspect) clazz.getConstructor().newInstance();
            } catch (Exception e) {
                e.printStackTrace();
                return null;
            }

        }).filter(Objects::nonNull).collect(Collectors.toList());

        var inst = cls.getConstructor().newInstance();

        return (T) Proxy.newProxyInstance(
                cls.getClassLoader(),
                cls.getInterfaces(),
                new InvocationHandler() {
                    @Override
                    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                        for (var aspect : aspectInsts){
                            aspect.before();
                        }
                        var result = method.invoke(inst);
                        for (var aspect : aspectInsts){
                            aspect.after();
                        }
                        return result;
                    }
                });
    }
}

package com.miracle.study.aspect;

/**
 * 切面实现类
 * @author Miracle
 * @date 2021/4/4 12:46
 */
public class TimeUsageAspect implements Aspect{

    long start;

    @Override
    public void before() {
        start = System.currentTimeMillis();
    }

    @Override
    public void after() {
        var usage = System.currentTimeMillis() - start;
        System.out.format("time usage : %dms\n", usage);

    }
}

测试:

package com.miracle.study.aspect;

import org.junit.jupiter.api.Test;

import java.lang.reflect.InvocationTargetException;

/**
 * 测试
 * @author Miracle
 * @date 2021/4/4 17:42
 */
public class ProxyExampleTest {
    
    @Test
    public void test_proxy() throws InvocationTargetException, NoSuchMethodException, InstantiationException, IllegalAccessException, InterruptedException {
        IOrder order = Aspect.getProxy(Order.class, "com.miracle.study.aspect.TimeUsageAspect");
        order.pay();
        order.show();
    }
}

参考资料

https://www.cnblogs.com/wobuchifanqie/p/9991342.html
https://blog.csdn.net/u012326462/article/details/81293186

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

萌白在努力

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值