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类方法