什么是基于注解的切面实现
我们使用切面来非侵入式操作程序方法,常用的场景如日志记录、权限判断等。
下面我实现权限判断的切面。
分析:
要实现基于注解的切面,我们要定义“注解”,定义切面,定义权限验证,定义权限返回。
- 定义注解:PermissionCheck.java
@Target({ElementType.TYPE, ElementType.METHOD}) // 注解类型, 级别
@Retention(RetentionPolicy.RUNTIME) // 运行时注解
public @interface PermissionCheck {
String value() default "";
}
- 定义权限校验方法,这里定义 AuthService 和它的实现。
public interface AuthService {
boolean checkAccess();
}
@Service
@Transactional(readOnly = true, rollbackFor = Exception.class)
public class AuthServiceImpl implements AuthService {
@Override
public boolean checkAccess() {
return true;
}
}
根据需要可改写 checkAccess 方法。
- 定义一个advice 来处理校验结果:
@ControllerAdvice
public class PermissionAdvice {
@ExceptionHandler(value = PermissionCheckException.class)
@ResponseStatus(HttpStatus.OK)
@ResponseBody
public String dealWithPermissionCheckException(PermissionCheckException exception) {
System.out.println(exception.getMessage());
return exception.getMessage();
}
public String dealWithPermissionCheckException() {
return null;
}
- 接下来就是组合进切面了
@Aspect // 切面标识
@Component // 交给spring容器管理
public class PermissionAspect {
@Autowired
private AuthService authService;
/**
* 选取切入点为自定义注解
*/
@Pointcut("@annotation(com.honeywen.credit.annotation.PermissionCheck)")
public void permissionCheck(){}
@Before(value = "permissionCheck()")
public void before(JoinPoint joinPoint) throws NoSuchMethodException {
// 获取连接点的方法签名对象
Signature signature = joinPoint.getSignature();
if (!(signature instanceof MethodSignature)) {
throw new PermissionCheckException("user permission check failed , stop the request!");
}
MethodSignature methodSignature = (MethodSignature) signature;
Object target = joinPoint.getTarget();
// 获取到当前执行的方法
Method method = target.getClass().getMethod(methodSignature.getName(), methodSignature.getParameterTypes());
// 获取方法的注解
PermissionCheck annotation = method.getAnnotation(PermissionCheck.class);
System.out.println(annotation);
System.out.println("我是在执行业务逻辑之前");
// 权限检查
authService.checkAccess();
}
@After(value = "permissionCheck()")
public void after(JoinPoint joinPoint) {
System.out.println("我是在执行业务逻辑之后");
}
}
总结:
主要过程在定义切面, 然后就是切面在哪里执行:
@Pointcut("@annotation(com.honeywen.credit.annotation.PermissionCheck)")
public void permissionCheck(){}
这里声明的是标注 @PermissionCheck 注解的方法执行。