美文网首页
SpringBoot之切面实践

SpringBoot之切面实践

作者: 程序员小白成长记 | 来源:发表于2020-06-23 10:44 被阅读0次

术语GET

Pointcut: a predicate that matches join points. Advice is associated with a pointcut expression and runs at any join point matched by the pointcut

Advice: action taken by an aspect at a particular join point.

SpringAop vs AspectJ

参考

spring aop官方文档
使用spring Aop实现后台权限验证
springAop实现简单的权限角色验证
说说 Spring AOP 中 @Aspect 的高级用法

二、案例

image.png

2.1 注解实现切面


1. 注解Verify

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface Verify {
}

2. 切面VerifyAspect(切入点+通知)
【注意】@Aspect、@Component注解

@Aspect
@Component
public class VerifyAspect {

    /**
     * 切入点,已经被增强的连接点
     */
    @Pointcut("@annotation(com.example.demo.aop.annotation.Verify)")
    public void pointcut(){
        System.out.println("pointcut()");
    }

    /**
     * 前置通知
     */
    @Before("pointcut()")
    public void beforePointCut(){
        System.out.println("beforePoint()");
    }
}

3. 测试Controller

@RestController
public class TestController {

    @Verify
    @RequestMapping(value="/aspect/test", method = RequestMethod.GET)
    public void test(){
        System.out.println("test()");
    }
}

4. pom.xml

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-aop</artifactId>
</dependency>
image.png
5. 结果验证
GET /aspect/test
返回结果:
beforePoint()
test()

2.1 注解实现切面(获取拦截方法参数,注解信息)


image.png
1. 自定义注解 VerifyAnnotation
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface VerifyAnnotation {
    // default 后只能是常量
    int roleType() default 0;
}

2.编写切面 VerifyAnnotationAspect

import com.example.demo.aop.annotation.VerifyAnnotation;
import org.apache.commons.lang3.ArrayUtils;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.Signature;
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.stereotype.Component;

import java.lang.reflect.Method;
import java.lang.reflect.Parameter;

@Aspect
@Component
public class VerifyAnnotationAspect {

    /**
     * 切入点,已经被增强的连接点
     */
    @Pointcut("@annotation(com.example.demo.aop.annotation.VerifyAnnotation)")
    public void pointcut(){
        System.out.println("pointcut()");
    }

    /**
     * 前置通知
     */
    @Before("pointcut()")
    public void beforePointCut(JoinPoint joinPoint) throws NoSuchMethodException {
        System.out.println("beforePoint()");
        // 拦截的对象
        // eg: TestController@5809
        Object target = joinPoint.getTarget();
        // 拦截的方法名称
        String methodName = joinPoint.getSignature().getName();
        // 拦截的方法参数,不包含字段名,方法参数*值*数组(下标与传参下标对应)
        // eg: args[0] = 1
        Object[] args = joinPoint.getArgs();
        // 拦截方法参数类型(下标与传参下标对应)
        Class<?>[] parameterTypes = ((MethodSignature) joinPoint.getSignature()).getMethod().getParameterTypes();
        // 通过方法名称,传参类型获得方法,防止重载
        Method method = target.getClass().getMethod(methodName, parameterTypes);
        // parameter[0].name(id)
        // parameter[0].getType()(int)
        Parameter[] parameter = method.getParameters();
        // 方法签名(方法的调用类型、方法名称、参数名称、参数类型、返回类型)
        Signature signature = joinPoint.getSignature();
        MethodSignature methodSignature = (MethodSignature) signature;
        // 参数名称数组
        // eg: parameterNames[0] = "id"
        String[] parameterNames = methodSignature.getParameterNames();
        int idIndex = ArrayUtils.indexOf(parameterNames, "id");
        int id = (int)args[idIndex];
        // 获取方法上中的注解
        VerifyAnnotation verifyAnnotation = method.getAnnotation(VerifyAnnotation.class);
        int roltType = verifyAnnotation.roleType();
        return;
    }
}

3. TestController

import com.example.demo.aop.annotation.VerifyAnnotation;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class TestController {

    @VerifyAnnotation(roleType = 0)
    @RequestMapping(value="/aspect/test/{id}", method = RequestMethod.GET)
    public void test(@PathVariable int id){
        System.out.println("test()");
        System.out.println("id:" + id);
    }
}

4.访问
GET /aspect/test/1
可以通过打断点查看是否获取相应信息

相关文章

网友评论

      本文标题:SpringBoot之切面实践

      本文链接:https://www.haomeiwen.com/subject/biiffktx.html