- 缓存权限校验结果
- 对于经常调用且权限校验逻辑不变的方法,可以使用缓存机制。例如,使用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;
}
}
- 合并重复校验逻辑
- 将相同的权限校验逻辑提取到一个公共方法中。例如,在代理类中,不同方法的权限校验可能都依赖于用户角色和操作类型,可以将这部分通用逻辑封装起来。
- 示例代码:
public class PermissionChecker {
public static boolean checkCommonPermission(User user, String operation) {
// 检查用户角色和操作权限
if ("admin".equals(user.getRole()) || "manager".equals(user.getRole())) {
return true;
}
return false;
}
}
- 合理设计代理链
- 责任链模式:使用责任链模式来处理代理链。每个代理对象负责一部分权限校验逻辑,依次传递请求。这样可以避免重复校验,并且使得代理逻辑更加清晰。
- 示例代码:
// 抽象权限校验处理器
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;
}
}
- 使用AspectJ替代动态代理(如果可行)
- AspectJ是一个基于字节码增强的AOP框架,相比JDK动态代理和CGLIB动态代理,在性能上可能更有优势,尤其是对于大量方法的切面处理。
- 配置AspectJ的方式(以Maven项目为例):
<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("没有权限");
}
}