使用IDEA创建SpringBoot项目的自定义注解

目录

准备好springboot项目

在pringboot项目添加需要的依赖

手动创建一个自定义注解

AOP配置

控制层调用自定义注解

首先声明本人使用的是IDEA开发工具

在pom.xml文件中添加AOP的依赖:

        
			org.springframework.boot
			spring-boot-starter-aop
	

创建一个自定义的注解 

使用IDEA创建SpringBoot项目的自定义注解_第1张图片

 创建后是这样的

package com.ucap.repository.web.testAspect;

import org.springframework.core.Ordered;
import org.springframework.core.annotation.Order;

import java.lang.annotation.*;

/**
 * @Description: TODO
 * @Author: dongxj
 * @Date: 2018-11-22 15:00
 */

@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
@Order(Ordered.HIGHEST_PRECEDENCE)
public @interface PermisionAnnotation {
    String value() default "";
}

 自定义注解需要用到元注解,加入自定义注解需要的注释

@Documented  //注解表明制作javadoc时,是否将注解信息加入文档。如果注解在声明时使用了@Documented,则在制作javadoc时注解信息会加入javadoc。

@Target(ElementType.TYPE) //接口、类、枚举、注解
@Target(ElementType.FIELD) //字段、枚举的常量
@Target(ElementType.METHOD) //方法
@Target(ElementType.PARAMETER) //方法参数
@Target(ElementType.CONSTRUCTOR) //构造函数
@Target(ElementType.LOCAL_VARIABLE)//局部变量
@Target(ElementType.ANNOTATION_TYPE)//注解
@Target(ElementType.PACKAGE) ///包

@Retention(RetentionPolicy.SOURCE) —— 这种类型的Annotations只在源代码级别保留,编译时就会被忽略

@Retention(RetentionPolicy.CLASS) —— 这种类型的Annotations编译时被保留,在class文件中存在,但JVM将会忽略
@Retention(RetentionPolicy.RUNTIME) —— 这种类型的Annotations将被JVM保留,所以他们能在运行时被JVM或其他使用反射机制的代码所读取和使用.

AOP配置

使用IDEA创建SpringBoot项目的自定义注解_第2张图片

@Service用于标注业务层组件

@Controller用于标注控制层组件(如struts中的action)

@Repository用于标注数据访问组件,即DAO组件

@Component泛指组件,当组件不好归类的时候,我们可以使用这个注解进行标注。

@Aspect//切面

@Pointcut//定义需要切面的地方,表达式参数(https://blog.csdn.net/elim168/article/details/78150438)

@annotation//当执行的方法上拥有指定的注解时生效。

 

@After      最后执行,优先级是最后

@Before   在执行proceed方法之前,先执行,优先级是2

@Around  最先先执行,优先级是1

看如下代码。

package com.ucap.repository.web.testAspect;

import com.ucap.repository.base.data.Data;
import com.ucap.repository.log.aspect.LogAnnotation;
import com.ucap.repository.utils.Validator;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.core.LocalVariableTableParameterNameDiscoverer;
import org.springframework.core.annotation.Order;
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 org.springframework.web.multipart.MultipartFile;

import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * @Description: TODO
 * @Author: dongxj
 * @Date: 2018-11-22 15:07
 */
@Component
@Aspect
@Order(10)
public class PermisionAspect {

    @Pointcut("@annotation(PermisionAnnotation)")
    private void entryPoint0() { }

    /**
     * 定制一个环绕通知
     * @param joinPoint
     */
    @Around("entryPoint0()&&@annotation(permisionAnnotation)")
    public void advice( ProceedingJoinPoint joinPoint,PermisionAnnotation permisionAnnotation) throws Throwable {
        System.out.println("Around Begin");
        String value=permisionAnnotation.value();//获取注解中的传值
        Method method = getMethod(joinPoint);
        LogAnnotation logAnnotation = method.getAnnotation(LogAnnotation.class);
        joinPoint.proceed();//执行到这里开始走进来的方法体(必须声明)
        System.out.println("Around End");
    }

    private Method getMethod(JoinPoint joinPoint) throws Exception {
        MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();
        Method method = methodSignature.getMethod();
        return method;
    }


    //当想获得注解里面的属性,可以直接注入改注解
    //方法可以带参数,可以同时设置多个方法用&&
    @Before("oldboy()")
    public void record(JoinPoint joinPoint) {
        System.out.println("Before");
    }
 
    @After("oldboy()")
    public void after() {
        System.out.println("After");
    }

}

ProceedingJoinPoint和JoinPoint说明
AspectJ使用org.aspectj.lang.JoinPoint接口表示目标类连接点对象,如果是环绕增强时,使用org.aspectj.lang.ProceedingJoinPoint表示连接点对象,该类是JoinPoint的子接口。任何一个增强方法都可以通过将第一个入参声明为JoinPoint访问到连接点上下文的信息。我们先来了解一下这两个接口的主要方法:

1.JoinPoint 
 java.lang.Object[] getArgs():获取连接点方法运行时的入参列表; 
 Signature getSignature() :获取连接点的方法签名对象; 
 java.lang.Object getTarget() :获取连接点所在的目标对象; 
 java.lang.Object getThis() :获取代理对象本身; 
2.ProceedingJoinPoint 
ProceedingJoinPoint继承JoinPoint子接口,它新增了两个用于执行连接点方法的方法: 
 java.lang.Object proceed() throws java.lang.Throwable:通过反射执行目标对象的连接点处的方法; 
 java.lang.Object proceed(java.lang.Object[] args) throws java.lang.Throwable:通过反射执行目标对象连接点处的方法,不过使用新的入参替换原来的入参。

目录结构是这样的

在controller中调用

通过调用,就会将注解中的参数值带入到AOP的环绕通知,实现权限的拦截。

 

总结

Around最先执行

然后在执行proceed方法之前,Before先执行

然后才是方法体本身

然后是Around再结尾

最后才是After

 

 

你可能感兴趣的:(注解,自定义注解)