一、基本注解
- @Override : 重写
- @Deprecated : 已过时的
- @SuppressWarnings(value = “unchecked”) :抑制编辑器报错
二、元注解
元注解用于修饰其他的注解
-
@Retention:定义注解的保留策略
-
@Retention(RetentionPolicy.SOURCE)
注解仅存在于源码中,在 class 字节码文件中不包含 -
@Retention(RetentionPolicy.CLASS)
默认的保留策略,注解会在 class 字节码文件中存在,但运行时无法获得, -
@Retention(RetentionPolicy.RUNTIME)
注解会在 class 字节码文件中存在,在运行时可以通过反射获取到
@Target:指定被修饰的 Annotation 可以放置的位置 (被修饰的目标)
- @Target(ElementType.TYPE) :接口、类
- @Target(ElementType.FIELD):属性
- @Target(ElementType.METHOD):方法
- @Target(ElementType.PARAMETER) :方法参数
- @Target(ElementType.LOCAL_VARIABLE) : 局部变量
- @Target(ElementType.ANNOTATION_TYPE): 注解
-
@Target(ElementType.PACKAGE) : 包
注:可以指定多个位置,例如:
-
@Target ({ElementType.METHOD, ElementType.TYPE}),也就是此注解可以在方法和类上面使用
@Inherited:指定被修饰的 Annotation 将具有继承性
- @Documented:指定被修饰的该 Annotation 可以被 javadoc 工具提取成文档.
三、注解分类
根据 Annotation 是否包含成员变量,可以把 Annotation 分为两类:
-
标记 Annotation:
没有成员变量的 Annotation; 这种 Annotation 仅利用自身的存在与否来提供信息 -
元数据 Annotation:
包含成员变量的 Annotation; 它们可以接受 (和提供) 更多的元数据;
四、注解开发
1. 注解的定义
使用 @interface 关键字,其定义过程与定义接口非常类似,需要注意的是:Annotation 的成员变量在 Annotation 定义中是以无参的方法形式来声明的,其方法名和返回值类型定义了该成员变量的名字和类型, 而且我们还可以使用 default 关键字为这个成员变量设定默认值
@Documented
@Target({ElementType.TYPE,ElementType.METHOD})
@Inherited
@Retention(RetentionPolicy.RUNTIME)
public @interface Annotation1 {
String param1() default "";
String param2() default "";
}
测试:
@Controller
@RequestMapping("/test")
@Annotation1(param1 = "1")
public class TestController extends BaseController {
@Autowired
private Business business;
@GetMapping("/test")
@ResponseBody
public String add()
{
business.doSomeThing("测试测试");
return "111";
}
}
public static void main(String[] args) {
/**
* 获取目标上所有注解
* getAnnotations
* */
for (Annotation a : TestController.class.getAnnotations()) {
if(a instanceof Annotation1){
System.out.println("getAnnotations:"+((Annotation1) a).param1());
}
}
/**
* 获取目标上指定注解
* getAnnotation
*/
Annotation1 a = TestController.class.getAnnotation(Annotation1.class);
if(a!=null){
System.out.println("getAnnotation:"+a.param2());
}
/**
* 判断目标上是否含有指定注解
* isAnnotationPresent
*/
//获取这个注解类
Class c=Class.forName("com.yunfang.qjep.test.TestController");
//判断类上面是否有标记了@Annotation1
if(c.isAnnotationPresent(Annotation1.class)){
Annotation1 a_ = TestController.class.getAnnotation(Annotation1.class);
System.out.println(a_.param1());
}else{
System.out.println("该类上无指定注解");
}
//判断方法上面是否有标记了@Annotation1
Method method = c.getDeclaredMethod("add",String.class,String.class);
if(method.isAnnotationPresent(Annotation1.class)){
Annotation1 a_ = method.getAnnotation(Annotation1.class);
System.out.println(a_.param1());
}else{
System.out.println("该方法上无指定注解");
}
//判断属性上面是否有标记了@Annotation1
Field field = c.getDeclaredField("business");
if(field.isAnnotationPresent(Annotation1.class)){
Annotation1 a_ = field.getAnnotation(Annotation1.class);
System.out.println(a_.param1());
}else{
System.out.println("该属性上无指定注解");
}
}
2. 自定义注解切面使用
切点入口:
@GetMapping("/test")
@ResponseBody
@Annotation1(param1 = "param1",param2 = "param2")
public String add(String param1, String param2)
{
business.doSomeThing("测试测试");
return "111";
}
切面:
@Aspect
@Component
public class TestAspect {
@Before(value="@annotation(com.yunfang.qjep.test.Annotation1)")
public void before(JoinPoint joinPoint){
System.out.println("@Before通知执行................................");
ServletRequestAttributes attributes =
(ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
HttpServletRequest request = attributes.getRequest();
//获取详细方法签名对象
MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();
Method method = methodSignature.getMethod();//获取到方法对象
Annotation1 action = method.getAnnotation(Annotation1.class); //获取方法上的注解
String param1 = action.param1();//获取注解参数param1的值
String param2 = action.param2();//获取注解参数param2的值
String param1_val = request.getParameter(param1);//从request中获取方法参数param1的值
String param2_val = request.getParameter(param2);//从request中获取方法参数param1的值
System.out.println("before通知执行结束.........................");
}
}
结果: