Annotation注解在java项目中使用很普遍,例如@Entity注解实体类并结合spring之后,当程序一运行就会自动创建@Entity注解所对应的数据库表,是不是很神奇呢?下面就让我们使用java来自定义注解吧!
首先来了解下自定义注解所必须要熟悉的几个注解(注解的注解):
1:@Target注解,该注解的作用就是告诉java你的注解将在什么地方起到作用,放在哪个位置,参数是名为ElementType的枚举类型,如下。
@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) //包 注解
2:@Rentation注解: 表示该注解一直会陪伴class到哪个时候,参数RetentionPolicy也是枚举类型,如下:
// 注解仅存在于源码中,在class字节码文件中不包含 @Retention(RetentionPolicy.SOURCE) // 默认的保留策略,注解会在class字节码文件中存在,但运行时无法获得, @Retention(RetentionPolicy.CLASS) // 注解会在class字节码文件中存在,在运行时可以通过反射获取到 @Retention(RetentionPolicy.RUNTIME)
3:@Document注解:说明该注解将被包含在javadoc中
4:@Inherited注解:说明子类可以继承父类中的该注解
--------说了这么多,下面我们来学习如何自定义注解吧!我们将自定义2个注解-----------
一:自定义@HelloWorld注解,注意interface这里,如果缺少了@符号就变成了java接口定义了,就不是自定义注解了:
package com.baidu; import java.lang.annotation.Documented; import java.lang.annotation.ElementType; import java.lang.annotation.Inherited; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; @Documented @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.METHOD) @Inherited public @interface HelloWorld { public String name()default ""; }
二:自定义@Yts注解:
package com.baidu; import java.lang.annotation.Documented; import java.lang.annotation.Retention; import java.lang.annotation.Target; import java.lang.annotation.ElementType; import java.lang.annotation.RetentionPolicy; @Documented @Target({ElementType.TYPE,ElementType.METHOD}) //多个作用位置用逗号隔开 @Retention(RetentionPolicy.RUNTIME) public @interface Yts { public enum YtsType{util,entity,service,model} public YtsType classType() default YtsType.util; }
三:在SayHello.java类中使用我们自定义好的注解,代码如下。
package com.baidu; import com.baidu.Yts.YtsType; //类注解 @Yts(classType=YtsType.util) public class SayHello { //方法注解 @HelloWorld(name = "小明 ") @Yts public void sayHello(String name){ if(name == null || name.equals("")){ System.out.println("hello world!"); }else{ System.out.println(name + "说 hello world!"); } } }
四:利用java反射获取获取自定义注解上的参数并运行注解下面的方法,代码如下。
package com.baidu; import java.lang.reflect.Method; import com.baidu.Yts.YtsType; public class ParseAnnotation { public ParseAnnotation() throws Exception{ super(); parseType(SayHello.class); parseMethod(SayHello.class); } //反射获取方法注解 public static void parseMethod(Class<?> clazz) throws Exception{ Object obj = clazz.getConstructor(new Class[]{}).newInstance(new Object[]{}); for(Method method : clazz.getDeclaredMethods()){ //获取@HelloWorld注解 HelloWorld say = method.getAnnotation(HelloWorld.class); String name = ""; if(say != null){ //获取获取@HelloWorld注解上的name属性值 name = say.name(); //调用方法,并将name值赋值给方法参数 method.invoke(obj, name); } //获取@Yts注解 Yts yts = (Yts)method.getAnnotation(Yts.class); if(yts != null){ if(YtsType.util.equals(yts.classType())){ System.out.println("这是一个util类方法"); }else{ System.out.println("这是一个其它类方法"); } } } } //反射获取类注解 public static void parseType(Class<?> clazz) throws Exception{ //获取类上的注解@Yts Yts yts = (Yts) clazz.getAnnotation(Yts.class); if(yts != null){ if(YtsType.util.equals(yts.classType())){ System.out.println("这是一个util类"); }else{ System.out.println("这是一个其它类"); } } } }
五:测试我们自定义的注解,兴奋的一刻开始了。
package com.baidu; public class AnnTestDemo { public static void main(String[] args) throws Exception { //使用方法1:new对象之后自动调用方法,类似@Entity注解自动创建数据库表的原理 ParseAnnotation parse = new ParseAnnotation(); //方法2:静态调用 // ParseAnnotation.parseType(SayHello.class); // ParseAnnotation.parseMethod(SayHello.class); } }
以上输出的结果如下。
这是一个util类 小明 说 hello world! 这是一个util类方法