切面注解
bash
import com.bn.document.constants.FmDeptCatalogueConstants;
import java.lang.annotation.*;
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface FmDeptCatalogueAopAnnotation {
/**
* 权限类型
*/
FmDeptCatalogueConstants value();
/**
* 目录id
*/
String catalogueId() ;
}
切面类 (整个类) 重点代码在下面
bash
package com.bn.document.aop;
import com.bn.document.constants.FmDeptCatalogueConstants;
import com.bn.document.po.FmDeptCataloguePo;
import com.bn.document.po.LoginUser;
import com.bn.document.service.FmDeptCatalogueService;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.DefaultParameterNameDiscoverer;
import org.springframework.core.ParameterNameDiscoverer;
import org.springframework.expression.EvaluationContext;
import org.springframework.expression.ExpressionParser;
import org.springframework.expression.spel.standard.SpelExpressionParser;
import org.springframework.expression.spel.support.StandardEvaluationContext;
import org.springframework.stereotype.Component;
import java.lang.reflect.Method;
import java.util.List;
@Aspect
@Component
public class MyAspect {
private final ExpressionParser parser = new SpelExpressionParser();
private final ParameterNameDiscoverer parameterNameDiscoverer = new DefaultParameterNameDiscoverer();
@Autowired
private FmDeptCatalogueService fmDeptCatalogueService;
/**
* 定义切入点:拦截带有 @MyCustomAnnotation 的方法
*/
@Pointcut("@annotation(com.bn.document.aop.FmDeptCatalogueAopAnnotation)")
public void cataloguePointcut() {}
/**
* 环绕增强:获取注解中的权限类型,检查用户权限
*/
@Around("cataloguePointcut()")
public Object aroundAdvice(ProceedingJoinPoint joinPoint) throws Throwable {
// 获取方法上的注解
FmDeptCatalogueAopAnnotation annotation = ((MethodSignature) joinPoint.getSignature())
.getMethod()
.getAnnotation(FmDeptCatalogueAopAnnotation.class);
if (annotation == null) {
return joinPoint.proceed(); // 没有注解直接放行
}
// 获取权限类型
FmDeptCatalogueConstants permissionType = annotation.value();
// 获取方法参数值
Object[] args = joinPoint.getArgs();
LoginUser loginUser = null;
// 遍历参数列表,提取 LoginUser 和 catalogueId
for (Object arg : args) {
if (arg instanceof LoginUser) {
loginUser = (LoginUser) arg;
}
}
// 开始解析 SpEL 表达式
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
Method method = signature.getMethod();
// 获取方法参数名 + 参数值,用于构建 SpEL 上下文
String[] paramNames = parameterNameDiscoverer.getParameterNames(method);
// 构建 EvaluationContext,并绑定参数
EvaluationContext context = new StandardEvaluationContext();
if (paramNames != null && args.length > 0) {
for (int i = 0; i < paramNames.length; i++) {
context.setVariable(paramNames[i], args[i]); // 绑定参数
}
}
// 解析表达式中的目录ID
String catalogueIdExpr = annotation.catalogueId();
Long catalogueId = parser.parseExpression(catalogueIdExpr).getValue(context, Long.class);
// 判断参数是否为空
if (loginUser == null || loginUser.getDeptId() == null) {
throw new SecurityException("登录信息错误");
}
if (catalogueId == null || catalogueId <= 0) {
throw new SecurityException("目录ID不能为空");
}
// 调用服务层查询权限
List<FmDeptCataloguePo> result = fmDeptCatalogueService.getFmDeptCataloguePoWithDeptId(
loginUser.getDeptId(),
catalogueId,
permissionType
);
// 如果权限不存在
if (result == null || result.isEmpty()) {
throw new SecurityException("您没有【" + permissionType.getDes() + "】权限");
}
// 否则放行
return joinPoint.proceed();
}
}
重点【开始解析 SpEL 表达式】
bash
// 开始解析 SpEL 表达式
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
Method method = signature.getMethod();
// 获取方法参数名 + 参数值,用于构建 SpEL 上下文
String[] paramNames = parameterNameDiscoverer.getParameterNames(method);
// 构建 EvaluationContext,并绑定参数
EvaluationContext context = new StandardEvaluationContext();
if (paramNames != null && args.length > 0) {
for (int i = 0; i < paramNames.length; i++) {
context.setVariable(paramNames[i], args[i]); // 绑定参数
}
}
// 解析表达式中的目录ID
String catalogueIdExpr = annotation.catalogueId();
Long catalogueId = parser.parseExpression(catalogueIdExpr).getValue(context, Long.class);
使用
1.获取对象中的属性值
bash
@Override
@Transactional(rollbackFor = Exception.class)
@FmDeptCatalogueAopAnnotation(value = FmDeptCatalogueConstants.MODIFY_PERMISSION, catalogueId = "#sysFileCataloguePo.parentId")
public CommonResponse insertSub(SysFileCataloguePo sysFileCataloguePo,LoginUser loginUser) {
}
1.1 结果

2.直接取值
bash
@Override
@FmDeptCatalogueAopAnnotation(value = FmDeptCatalogueConstants.DETAILS_PERMISSION, catalogueId = "#id")
public CommonResponse getSub(Long id, LoginUser loginUser) {
}
2.1 结果
