SpringBoot之自定义注解(基于AOP实现)

步骤

  • 使用@interface 自定义注解
  • 编写注解处理切面类

原理

通过注解来指定切点

缺陷

使用Spring AOP实现的切面类只能作用在方法上,所以,基于Spring AOP的自定义注解也只能添加在方法上

代码示例

完整参考代码github

自定义注解

1
2
3
4
5
6
7
8
9
10
11
import org.springframework.stereotype.Component;

import java.lang.annotation.*;

@Target({ElementType.METHOD}) //基于Spring AOP的注解只能作用在方法上
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Component
public @interface Girl {
String value() default "";
}

定义处理注解的切面

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.stereotype.Component;

@Aspect
@Component
public class GirlAnnotationAop {

/**
* @Before 表示在方法执行前运行切面逻辑
* value值定义了切点,此次使用注解来指定切点
* @annotation(参数) 如果自定义的注解不需要参数,则可以为@annotation(类名)
* && 连接多个指定切点的条件
* args(name) 用来获取被注解的方法的参数
*/
@Before(value="@annotation(girl) && args(name)")
public void dofore(JoinPoint joinPoint,Girl girl, String name) {
System.out.println("the girl is " + girl.value());
System.out.println("she will say hello to " + name);
}
}

注解使用类

1
2
3
4
5
6
7
8
9
10
import org.springframework.stereotype.Component;

@Component
public class HelloGirl {

@Girl("小红")
public void sayHello(String name) {
System.out.println("hello, " + name);
}
}

测试类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
import com.markey.annotations.Girl.HelloGirl;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;

@RunWith(SpringRunner.class)
@SpringBootTest
public class HelloGirlTest {

@Autowired
HelloGirl helloGirl;

@Test
public void HelloGirlTest() {
helloGirl.sayHello("world");
}
}

运行结果

Tips

  • 使用Spring AOP也可以处理属性注解,大概处理流程是编写切面处理某个类的某个方法,然后通过Java反射的方式再获得这个类的具有自定义注解的属性。但是这样的话,其实也是只有在调用这个方法的时候,注解才会生效。(可以参考我的上一篇文章
  • 使用AspectJ来做切面,就没有只能作用在方法上这种缺陷。