MST

星途 面试题库

面试题:Java动态代理在AOP复杂场景下的优化

在一个大型Java项目的AOP编程中,使用动态代理实现权限控制。当有大量不同类型的方法需要进行权限校验时,如何优化动态代理的性能并确保代理逻辑的正确性,例如如何避免重复的权限校验逻辑以及合理处理代理链?
22.1万 热度难度
编程语言Java

知识考点

AI 面试

面试题答案

一键面试
  1. 缓存权限校验结果
    • 对于经常调用且权限校验逻辑不变的方法,可以使用缓存机制。例如,使用Guava Cache或者Java自带的ConcurrentHashMap实现简单的缓存。
    • 示例代码(使用Guava Cache):
import com.google.common.cache.Cache;
import com.google.common.cache.CacheBuilder;
import java.util.concurrent.TimeUnit;

public class PermissionCache {
    private static final Cache<String, Boolean> permissionCache = CacheBuilder.newBuilder()
           .expireAfterWrite(10, TimeUnit.MINUTES)
           .build();

    public static boolean checkPermission(String methodSignature) {
        Boolean result = permissionCache.getIfPresent(methodSignature);
        if (result != null) {
            return result;
        }
        // 实际权限校验逻辑
        boolean hasPermission = performPermissionCheck(methodSignature);
        permissionCache.put(methodSignature, hasPermission);
        return hasPermission;
    }

    private static boolean performPermissionCheck(String methodSignature) {
        // 实际的权限校验代码
        return true;
    }
}
  1. 合并重复校验逻辑
    • 将相同的权限校验逻辑提取到一个公共方法中。例如,在代理类中,不同方法的权限校验可能都依赖于用户角色和操作类型,可以将这部分通用逻辑封装起来。
    • 示例代码:
public class PermissionChecker {
    public static boolean checkCommonPermission(User user, String operation) {
        // 检查用户角色和操作权限
        if ("admin".equals(user.getRole()) || "manager".equals(user.getRole())) {
            return true;
        }
        return false;
    }
}
  1. 合理设计代理链
    • 责任链模式:使用责任链模式来处理代理链。每个代理对象负责一部分权限校验逻辑,依次传递请求。这样可以避免重复校验,并且使得代理逻辑更加清晰。
    • 示例代码:
// 抽象权限校验处理器
abstract class PermissionHandler {
    protected PermissionHandler nextHandler;

    public void setNextHandler(PermissionHandler nextHandler) {
        this.nextHandler = nextHandler;
    }

    public abstract boolean checkPermission(User user, String method);

    public boolean handleRequest(User user, String method) {
        boolean result = checkPermission(user, method);
        if (result || nextHandler == null) {
            return result;
        }
        return nextHandler.handleRequest(user, method);
    }
}

// 具体权限校验处理器1
class RolePermissionHandler extends PermissionHandler {
    @Override
    public boolean checkPermission(User user, String method) {
        // 根据用户角色进行权限校验
        if ("admin".equals(user.getRole())) {
            return true;
        }
        return false;
    }
}

// 具体权限校验处理器2
class OperationPermissionHandler extends PermissionHandler {
    @Override
    public boolean checkPermission(User user, String method) {
        // 根据操作进行权限校验
        if ("read".equals(method)) {
            return true;
        }
        return false;
    }
}
  1. 使用AspectJ替代动态代理(如果可行)
    • AspectJ是一个基于字节码增强的AOP框架,相比JDK动态代理和CGLIB动态代理,在性能上可能更有优势,尤其是对于大量方法的切面处理。
    • 配置AspectJ的方式(以Maven项目为例):
      • pom.xml中添加AspectJ相关依赖:
<dependency>
    <groupId>org.aspectj</groupId>
    <artifactId>aspectjrt</artifactId>
    <version>1.9.7</version>
</dependency>
<dependency>
    <groupId>org.aspectj</groupId>
    <artifactId>aspectjweaver</artifactId>
    <version>1.9.7</version>
</dependency>
 - 编写AspectJ切面类:
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;

@Aspect
public class PermissionAspect {
    @Around("execution(* com.example..*(..))")
    public Object checkPermission(ProceedingJoinPoint joinPoint) throws Throwable {
        // 权限校验逻辑
        boolean hasPermission = true;
        if (hasPermission) {
            return joinPoint.proceed();
        }
        throw new RuntimeException("没有权限");
    }
}