切面怎样手写实现的呢,简单版


. 定义注解:@Aspect 和 @Order

import java.lang.annotation.*;

// 标记切面类
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface Aspect {
}

// 定义切面优先级(值越小,优先级越高)
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface Order {
    int value() default Integer.MAX_VALUE;
}
. 定义通知接口

public interface Advice {
    void before();
    void after();
}
. 定义切点接口

import java.lang.reflect.Method;

public interface Pointcut {
    boolean matches(Method method);
}
. 切面包装器(核心!)

import java.lang.annotation.Annotation;
import java.util.Arrays;

// 封装一个切面的所有信息
public class AspectWrapper implements Comparable<AspectWrapper> {
    private final Object aspectInstance; // 切面实例
    private final Advice advice;         // 通知逻辑
    private final Pointcut pointcut;     // 切点
    private final int order;             // 优先级

    public AspectWrapper(Object aspectInstance, Advice advice, Pointcut pointcut) {
        this.aspectInstance = aspectInstance;
        this.advice = advice;
        this.pointcut = pointcut;
        this.order = getAspectOrder(aspectInstance.getClass());
    }

    private int getAspectOrder(Class<?> clazz) {
        Order orderAnno = clazz.getAnnotation(Order.class);
        return orderAnno != null ? orderAnno.value() : Integer.MAX_VALUE;
    }

    public boolean matches(Method method) {
        return pointcut.matches(method);
    }

    public void before() { advice.before(); }
    public void after() { advice.after(); }

    @Override
    public int compareTo(AspectWrapper o) {
        return Integer.compare(this.order, o.order); // 从小到大排序
    }
}
. 多切面代理处理器(核心逻辑)

import java.lang.reflect.*;
import java.util.*;

public class MultiAspectProxy implements InvocationHandler {
    private final Object target;
    private final List<AspectWrapper> matchedAspects; // 匹配当前方法的切面列表

    public MultiAspectProxy(Object target, List<AspectWrapper> allAspects, Method method) {
        this.target = target;
        // 筛选出匹配当前方法的切面,并按优先级排序
        this.matchedAspects = allAspects.stream()
            .filter(aspect -> aspect.matches(method))
            .sorted()
            .collect(Collectors.toList());
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        if (matchedAspects.isEmpty()) {
            return method.invoke(target, args);
        }

        // 执行所有 before(按优先级从高到低)
        for (AspectWrapper aspect : matchedAspects) {
            aspect.before();
        }

        Object result;
        try {
            result = method.invoke(target, args);
        } finally {
            // 执行所有 after(按优先级从低到高 → 逆序)
            for (int i = matchedAspects.size() - 1; i >= 0; i--) {
                matchedAspects.get(i).after();
            }
        }

        return result;
    }

    // 创建代理对象的工厂方法
    public static Object createProxy(Object target, List<AspectWrapper> allAspects) {
        Class<?>[] interfaces = target.getClass().getInterfaces();
        if (interfaces.length == 0) {
            throw new IllegalArgumentException("目标类必须实现至少一个接口");
        }

        // 为每个方法创建独立的代理处理器(实际项目中可缓存)
        return Proxy.newProxyInstance(
            target.getClass().getClassLoader(),
            interfaces,
            new MultiAspectProxy(target, allAspects, null) // 注意:简化处理
        );
    }
}
⚠️ 注意:上述 createProxy 方法做了简化。严格来说,应在 invoke 中动态筛选匹配当前 method 的切面。完整版见下方优化。

. 优化版:动态匹配方法的代理
Java
编辑
// 改进的 InvocationHandler
public class MultiAspectProxy implements InvocationHandler {
    private final Object target;
    private final List<AspectWrapper> allAspects;

    public MultiAspectProxy(Object target, List<AspectWrapper> allAspects) {
        this.target = target;
        this.allAspects = allAspects;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        // 动态筛选匹配当前 method 的切面
        List<AspectWrapper> matched = allAspects.stream()
            .filter(aspect -> aspect.matches(method))
            .sorted()
            .collect(Collectors.toList());

        if (matched.isEmpty()) {
            return method.invoke(target, args);
        }

        // 执行 before(高优先级 → 低优先级)
        for (AspectWrapper aspect : matched) {
            aspect.before();
        }

        Object result;
        try {
            result = method.invoke(target, args);
        } finally {
            // 执行 after(低优先级 → 高优先级,逆序)
            for (int i = matched.size() - 1; i >= 0; i--) {
                matched.get(i).after();
            }
        }

        return result;
    }

    public static Object createProxy(Object target, List<AspectWrapper> allAspects) {
        return Proxy.newProxyInstance(
            target.getClass().getClassLoader(),
            target.getClass().getInterfaces(),
            new MultiAspectProxy(target, allAspects)
        );
    }
}
. 实现具体切面(示例)
切面1:日志切面(高优先级)

@Aspect
@Order(1)
public class LoggingAspect implements Advice {
    @Override
    public void before() {
        System.out.println("[LOG] 方法开始执行");
    }

    @Override
    public void after() {
        System.out.println("[LOG] 方法执行结束");
    }
}

// 日志切点:匹配所有方法
public class AllMethodsPointcut implements Pointcut {
    @Override
    public boolean matches(Method method) {
        return true;
    }
}
切面2:安全切面(低优先级)

@Aspect
@Order(2)
public class SecurityAspect implements Advice {
    @Override
    public void before() {
        System.out.println("[SECURITY] 权限检查通过");
    }

    @Override
    public void after() {
        System.out.println("[SECURITY] 清理安全上下文");
    }
}
. 测试多切面
业务接口与实现

public interface UserService {
    void saveUser(String name);
}

public class UserServiceImpl implements UserService {
    @Override
    public void saveUser(String name) {
        System.out.println("保存用户: " + name);
    }
}
主程序

public class MultiAspectDemo {
    public static void main(String[] args) {
        UserService userService = new UserServiceImpl();

        // 创建切面实例
        List<AspectWrapper> aspects = Arrays.asList(
            new AspectWrapper(new LoggingAspect(), new LoggingAspect(), new AllMethodsPointcut()),
            new AspectWrapper(new SecurityAspect(), new SecurityAspect(), new AllMethodsPointcut())
        );

        // 创建代理
        UserService proxy = (UserService) MultiAspectProxy.createProxy(userService, aspects);

        // 调用方法
        proxy.saveUser("张三");
    }
}

posted @ 2025-12-24 16:20  川流不息&  阅读(7)  评论(0)    收藏  举报