首先,注解是指对这个类、方法、变量、包等的说明(具体可以看java.lang.annotation.ElementType中的说明),如果是java定义的注解由Java来解析注解,如果是你自己定义的注解,则由程序员自己负责对注解进行解析,如果程序中对自己定义的注解没有进行解析,则该注解没有什么实际的意义。
注解有什么含义,取决于程序对改注解怎么解析,具体上代码(这个只是示例程序):
自己定义的注解
package annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target({ElementType.TYPE,ElementType.METHOD,ElementType.FIELD,ElementType.CONSTRUCTOR })
@Retention(RetentionPolicy.RUNTIME)
public @interface TestA {
String name() default "旁白";
int id() default 5;
Class gid();
}
使用注解的类
package annotation;
import java.util.HashMap;
import java.util.Map;
import annotation.TestA;
@TestA(name = "type",gid = Long.class)
public class UserAnnotation {
//私有属性不会被输出其注解
@TestA(name="param",id=1,gid=Long.class)
private Integer age;
//注解中没有对相关的属性赋值的话,使用默认值
@TestA(id=2,gid=Long.class)
public Integer age2;
//在age3中没有注释所以不会再控制台输出相关的注释信息
public Integer age3;
@TestA(name="param",id=2,gid=Long.class)
public Integer age4;
@TestA(name="construct",id=2,gid=Long.class)
public UserAnnotation(){}
@TestA(name="public method",id=3,gid=Long.class)
public void a()
{
Map m = new HashMap(0);
}
@TestA(name="private method",id=5,gid=Long.class)
private void c()
{
Map m = new HashMap(0);
}
public void b(Integer a )
{
}
}
解析注解的类
package annotation;
import java.lang.annotation.Annotation;
import java.lang.reflect.*;
public class ParseAnnotation {
public static void paraseTypeAnnotation()throws ClassNotFoundException
{
Class clazz = Class.forName("annotation.UserAnnotation");
Annotation[] annotations = clazz.getAnnotations();
for(Annotation annotation:annotations)
{
TestA testA = (TestA)annotation;
System.out.println("id= "+testA.id()+";name="+testA.name()+"; gid="+testA.gid());
}
}
public static void parseMethodAnnotation()
{
Method[] methods = UserAnnotation.class.getDeclaredMethods();
for(Method method : methods)
{
boolean hasAnnotation = method.isAnnotationPresent(TestA.class);
if(hasAnnotation)
{
TestA annotation = method.getAnnotation(TestA.class);
System.out.println("Method="+method.getName()+";id="+annotation.id()+";description="+annotation.name()+";gid="+annotation.gid());
}
}
}
public static void parseConstructAnnotation()
{
Constructor[] constructors = UserAnnotation.class.getConstructors();
for(Constructor constructor :constructors)
{
boolean hasAnnotation = constructor.isAnnotationPresent(TestA.class);
if(hasAnnotation)
{
TestA annotation = (TestA)constructor.getAnnotation(TestA.class);
System.out.println("constructor="+constructor.getName()+";id="+annotation.id()+";description="+annotation.name()+";gid="+annotation.gid());
}
}
}
public static void parseFieldAnnotation()
{
Field[] fields = UserAnnotation.class.getFields();
for(Field field : fields)
{
boolean hasAnnotation = field.isAnnotationPresent(TestA.class);
if(hasAnnotation)
{
TestA annotation = (TestA)field.getAnnotation(TestA.class);
System.out.println("field="+field.getName()+";id="+annotation.id()+";description="+annotation.name()+";gid="+annotation.gid());
}
}
}
public static void main(String[] args) throws ClassNotFoundException
{
paraseTypeAnnotation();
parseMethodAnnotation();
parseConstructAnnotation();
parseFieldAnnotation();
}
}
在解析注解的类中在获取注解时,需要做什么,这就决定了注解代表是什么意义。
for(Method method : methods)
{
boolean hasAnnotation = method.isAnnotationPresent(TestA.class);
if(hasAnnotation)
{
TestA annotation = method.getAnnotation(TestA.class);
System.out.println("Method="+method.getName()+";id="+annotation.id()+";description="+annotation.name()+";gid="+annotation.gid());
}
}
可以把以上的输出到控制台的代码修改为创建一个对象或者时直接退出程序,那么这个注解就代表创建对象或者时退出程序的注解。
如果你直接创建一个对象,并不解析注解那么注解就没有任何意义。
package annotation;
@TestA (gid=Long.class)
public class UserAnnotationTest
{
public static void main(String[] args)
{
System.out.println(new UserAnnotation().age2);
}
}
SpringBoot中的注解也是一样。在SpringBoot创建程序运行上下文的时候会去获取每个类上的注解,然后执行特定的逻辑(也就是这个注解代表的意义,如 “@Bean” 这个注解,他代表要把一个对象做为bean加入到spring容器中,那么在检索到类上有这个注解时就会创建这个类的实例,然后加入到容器中)。
列举几个SpringBoot中解析注解用到的类,用来参考。
ClassPathBeanDefinitionScanner.doScan()
ComponentScanAnnotationParser.parse()
ConfigurationClassParser.doProcessConfigurationClass()
总结:注解的意义关键在于你获取到注解后做什么操作,所做的操作就代表这个注解有什么意义,你完全可以起一个和你的操作没有任何关系的名字作为注解的名字(”@Bean“这个注解我完全可以定义为“@123”,让他执行和“@Bean”一样的操作。),但是不建议这么写程序。