java自定义注解【松思园】

一、引言

java注解是从jdk5引入的,jave中的注解分文 内置注解 自定义注解 ,而内置注解包括了普通的注解和元注解,元注解就是用来定义注解的注解,java底层注解的实现是反射机制来实现的。

什么是注解?

注解是源代码的元数据,可以理解为代码的标签。
可以简化配置;
增加代码的可读性;
提高系统的可维护性;

二、内置注解

1、普通注解

  • @Override:用于标识该方法继承自超类, 当父类的方法被删除或修改了,编译器会提示错误信息;
  • @Deprecated:表示该类或者该方法已经不推荐使用,已经过期了,如果用户还是要使用,会生成编译的警告;
  • @SuppressWarnings:用于忽略的编译器警告信息;
  • @Test:Junit测试;
  • @SafeVarargs:专门为抑制“堆污染”警告提供的;

2、元注解

  • @Retention:表示需要在什么级别保存该注释信息,用于描述注解的生命周期(即:被描述的注解在什么范围内有效);

    RetentionPoicy 有三个值:
    	1.SOURCE:在源文件中有效(即源文件保留)
    	2.CLASS:在class文件中有效(即class保留)
    	3.RUNTIME:在运行时有效(即运行时保留)
    
  • @Target:用于描述注解的使用范围(即:被描述的注解可以用在什么地方)

    ElementType 取值范围:
    	1.CONSTRUCTOR:用于描述构造器
    	2.FIELD:用于描述域
    	3.LOCAL_VARIABLE:用于描述局部变量
    	4.METHOD:用于描述方法
    	5.PACKAGE:用于描述包
    	6.PARAMETER:用于描述参数
    	7.TYPE:用于描述类、接口(包括注解类型) 或enum声明
    
  • @Document:说明该注解将被包含在javadoc中,是一个标记性注解;

  • @Inherited:阐述了某个被标注的类型是被继承的。如果一个使用了@Inherited修饰的annotation类型被用于一个class,则这个annotation将被用于该class的子类,是一个标记性注解;

三、自定义注解

1、@interface

public @interface 注解名 {定义体}

  • 注解参数的可支持数据类型:

    1.所有基本数据类型(int,float,boolean,byte,double,char,long,short)
    2.String类型
    3.Class类型
    4.enum类型
    5.Annotation类型
    6.以上所有类型的数组
    
  • Annotation类型里面的参数该怎么设定:

    1.只能用public或默认(default)这两个访问权修饰
    2.如果只有一个参数成员,最好把参数名称设为"value",后加小括号
    3.注解元素必须有确定的值,要么在定义注解的默认值中指定,要么在使用注解时指定,非基本类型的注解元素的值不可为null
    

2、代码练习

1. 自定义一个注解类 AnnotationDemo.class

package zidingyizhujie.annotation;
import enums.KeyCodesEnums;
import java.lang.annotation.*;

@Documented
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface AnnotationDemo {

	// key值  是个枚举类
	KeyCodesEnums key();

	// 名称
	String name();

	// 数据值
	String value() default "default";
}

枚举类:KeyCodesEnums.class

package enums;
public enum KeyCodesEnums {

	MONDAY("星期一"),
	TUESDAY("星期二"),
	WEDNESDAY("星期三"),
	THURSDAY("星期四"),
	FRIDAY("星期五"),
	SATURDAY("星期六"),
	SUNDAY("星期日");

	private String text;
	KeyCodesEnums(String text) {
		this.text = text;
	}
	public String getText() {
		return text;
	}
	public void setText(String text) {
		this.text = text;
	}

}

2. 定义一个使用该注解的类

package zidingyizhujie;

import enums.KeyCodesEnums;
import lombok.extern.slf4j.Slf4j;
import zidingyizhujie.annotation.AnnotationDemo;

/**
 * @project: java_syudy_moduls
 * @author: 13965
 * @date:2021/3/5 10:24
 * @description:
 */
@Slf4j
@AnnotationDemo(key = KeyCodesEnums.FRIDAY, name = "testClass")
public class AnnotationUseDemo {

	@AnnotationDemo(key = KeyCodesEnums.MONDAY, name = "testMethod")
	public void useAnnotationMethod() {
	}
}

四、自定义注解的解析

注解它本身是没什么用的,只有在恰当的时候,由外部程序解析才会产生作用

使用jdk反射去获取注解信息

Java通过反射机制解析注解,java在java.lang.reflect包下新增了AnnotatedElement接口, AnnotatedElement是所有注解元素的父接口,所有的注解元素都可以通过某个类反射获取AnnotatedElement对象,该对象有一下4个方法来访问Annotation信息。

(1)<T extends Annotation> T getAnnotation(Class<T> annotationClass)
     返回该程序元素上存在的、指定类型的注解,如果该类型注解不存在,则返回null。 
(2)Annotation[] getAnnotations():返回该程序元素上存在的所有注解。
(3)boolean isAnnotationPresent(Class<?extends Annotation> annotationClass)
    判断该程序元素上是否包含指定类型的注解,存在则返回true,否则返回false.
(4)Annotation[] getDeclaredAnnotations()
    返回直接存在于此元素上的所有注释。与此接口中的其他方法不同,该方法将忽略继承的注释。(如果没有注释直接存在于此元素上,则返回长度为零的一个数组。)该方法的调用者可以随意修改返回的数组;这不会对其他调用者返回的数组产生任何影响。

单元测试类 AnnotationTestDemo.class

package zidingyizhujie;

import lombok.extern.slf4j.Slf4j;
import org.junit.Test;
import zidingyizhujie.annotation.AnnotationDemo;

import java.lang.reflect.Method;

/**
 * @project: java_syudy_moduls
 * @author: 13965
 * @date:2021/3/5 15:18
 * @description:
 */
@Slf4j
public class AnnotationTestDemo {

	//	通过反射机制,解析自定义的注解  类
	@Test
	public void annotationClassResoveTest() {
		// 使用注解的类的反射对象
		Class<AnnotationUseDemo> annotationUseDemoClass = AnnotationUseDemo.class;
		// 自定义注解类的反射对象
		Class<AnnotationDemo> annotationDemoClass = AnnotationDemo.class;
		if (annotationUseDemoClass.isAnnotationPresent(annotationDemoClass)) {
			AnnotationDemo annotationDemo = annotationUseDemoClass.getAnnotation(annotationDemoClass);
			log.info("注解的参数>>>>>>name:" + annotationDemo.name());
			log.info("注解的参数>>>>>>value:" + annotationDemo.value());
			log.info("注解的参数>>>>>>key:" + annotationDemo.key());
		}

	}

	//	通过反射机制,解析自定义的注解  方法
	@Test
	public void annotationMethodResoveTest() {
		// 使用注解的类的反射对象
		Class<AnnotationUseDemo> annotationUseDemoClass = AnnotationUseDemo.class;
		// 自定义注解类的反射对象
		Class<AnnotationDemo> annotationDemoClass = AnnotationDemo.class;
		Method[] methods = annotationUseDemoClass.getMethods();
		for (Method method : methods) {
			if (method.isAnnotationPresent(annotationDemoClass)) {
				AnnotationDemo annotationDemo = annotationUseDemoClass.getAnnotation(annotationDemoClass);
				log.info("注解的参数>>>>>>name:" + annotationDemo.name());
				log.info("注解的参数>>>>>>value:" + annotationDemo.value());
				log.info("注解的参数>>>>>>key:" + annotationDemo.key());
			}
		}
	}

}

运行结果:因为我们在 AnnotationUseDemo 类中,类和方法均使用了注解 @AnnotationDemo ,这里的单元测试解析注解,获得结果为:

15:50:01.551 [main] INFO zidingyizhujie.AnnotationTestDemo - 注解的参数>>>>>>name:testClass
15:50:01.557 [main] INFO zidingyizhujie.AnnotationTestDemo - 注解的参数>>>>>>value:default
15:50:01.557 [main] INFO zidingyizhujie.AnnotationTestDemo - 注解的参数>>>>>>key:FRIDAY

15:50:01.559 [main] INFO zidingyizhujie.AnnotationTestDemo - 注解的参数>>>>>>name:testClass
15:50:01.560 [main] INFO zidingyizhujie.AnnotationTestDemo - 注解的参数>>>>>>value:default
15:50:01.560 [main] INFO zidingyizhujie.AnnotationTestDemo - 注解的参数>>>>>>key:FRIDAY
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值