springboot使用注解和aspectJ进行AOP编程

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.额外需要注意

在该类中调用自身的方法不会触发切面类处理

猜你喜欢

转载自blog.csdn.net/qq_24516549/article/details/88402679