1.注解类
先新建注解类
package cn.seiya2.modules.admin.annotation;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target({ ElementType.METHOD, ElementType.TYPE })
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface AdminCheck {
String type() default "AlreadyLogin";
}
@Target({ ElementType.METHOD, ElementType.TYPE })
表示该注解可以用在方法上或类上
@Retention(RetentionPolicy.RUNTIME)表示运行时使用
@Documented用于生成doc文档
2.切入点
package cn.seiya2.modules.admin.aspect;
import java.lang.reflect.Method;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import cn.seiya2.common.exception.RRException;
import cn.seiya2.common.utils.Constant;
import cn.seiya2.common.utils.MD5Utils;
import cn.seiya2.common.utils.RedisUtils;
import cn.seiya2.common.utils.UserRequest;
import cn.seiya2.modules.admin.annotation.AdminCheck;
@Aspect
@Configuration
public class AdminCheckAspect {
@Autowired
private RedisUtils RedisUtils;
@Pointcut("@annotation(cn.seiya2.modules.admin.annotation.AdminCheck)")
public void pointCut() {
}
@Pointcut("@within(cn.seiya2.modules.admin.annotation.AdminCheck)&&execution(public * *.*(..))")
public void typePointCut() {
}
}
两种织入点,一种是方法上加了注解,直接在方法上设置切入点,另一种是在类上加了注解,此时使用
@Pointcut("@within(cn.seiya2.modules.admin.annotation.AdminCheck)&&execution(public * *.*(..))")
切入加了注解的类中所有的public方法上
3.增强方法
@Before("pointCut()||typePointCut()")
public void doBefore(JoinPoint point) throws ClassNotFoundException {
checkSign();
Method method = getMethod(point);
AdminCheck adminCheck = method.getAnnotation(AdminCheck.class);
if (adminCheck == null) {
String classType = point.getTarget().getClass().getName();
Class<?> clazz = Class.forName(classType);
adminCheck = clazz.getAnnotation(AdminCheck.class);
}
String type = adminCheck.type();
switch (type) {
case "AlreadyLogin":
// 具体的业务方法
checkToken();
break;
case "NotyetLogin":
break;
default:
throw new RRException("注解参数错误");
}
}
private void checkToken() {
//具体的业务方法
}
private void checkSign() {
//具体的业务方法
}
private Method getMethod(JoinPoint point) {
MethodSignature methodSignature = (MethodSignature) point.getSignature();
Class<?> targetClass = point.getTarget().getClass();
try {
return targetClass.getMethod(methodSignature.getName(), methodSignature.getParameterTypes());
} catch (NoSuchMethodException e) {
return null;
}
}
先试图获取切入点方法上的注解参数,若为空再去获取该类上的注解参数,这样,就实现了方法上注解参数对该类注解参数的覆盖
4.额外需要注意
在该类中调用自身的方法不会触发切面类处理