一、java注解的作用:
java注解是在普通的java代码中加入的一些标记,使得java编译器在处理java代码时为java程序添加一些特性或功能,但并影响被修饰的java代码的作用。例如在一个类上添加一个@Component注解,表示spring扫描该类时创建该类的一个对象并注册为bean,加入spring容器,这样这个对象的生命周期由spring维护,程序内如果需要用该对象,可以向spring容器请求。但是删除@Component注解后,不会影响该类的原始功能。
二、 java注解的定义与应用:
java注解是一种特殊的接口,它的类型是@interface,每一个java注解都是java.lang.annotation.Annotation的子接口。
java5.0定义了四个元注解,用于注解自定义的注解,分别是:
@Documented,标记注解,用于标识一个注解是否可以被javadoc文档化;
@Inherited,标记注解,用于标识一个注解是否可以被继承;
@Target,指明了一个注解的作用对象,例如包、类、成员变量、成员方法、构造方法等,由枚举类型java.lang.annotation.ElementType指定;
@Retention,指明了一个注解的生命周期,也就是一个注解的有效时间范围,由枚举类型java.lang.annotation.RetentionPolicy指定。
一般情况下,java注解的定义格式是:
@interface 注解名{
类型名 函数名() default 默认值;
...
}
成员函数名也就是注解的属性名,属性类型也就是成员函数的返回类型,属性可以指定默认值。
java注解的应用方式是在被修饰的jav代码处添加如下代码:
@注解名
这样spring扫描到该注解后,会利用反射技术提取出相应注解,调用注解的成员方法,还可以结合注解处理器做进一步的处理。注解处理器通常要利用反射技术获取java类和成员的描述对象,例如Class<?>、Field、Method、Constructor等,再利用这些对象的成员方法getAnnotation查询并获取相应的注解对象,从而调用注解对象的成员方法获取注解信息,据此完成一定的功能。
三、注解处理器:
注解处理器就是一些利用针对java注解做处理的java类,其中的成员方法通常会根据java反射技术得到被修饰的java类的Class<?>对象、Constructor对象、Field对象、Method对象,还有java类所属的包Package。由于这些类都实现了java.lang.reflect.AnnotatedElement接口,可以调用该接口内声明的成员方法如getAnnotation从而获取相应的注解,再调用注解的成员方法获取注解信息,做进一步的处理。 被@Retention(value = RetentionPolicy.RUNTIME)修饰的注解在运行期起作用,通常需要用注解处理器。被RetentionPolicy.SOURCE RetentionPolicy.CLASS修饰的注解主要起标记作用。
四、java注解编程示例:
定义了三个java注解和它们的注解处理器,代码如下:
@Documented @Inherited @Target(value = { ElementType.FIELD,ElementType.METHOD}) @Retention(value = RetentionPolicy.RUNTIME) public @interface FruitColor { public enum Color{RED,GREEN,BLUE}; Color value() default Color.BLUE; }
@Documented @Inherited @Target(value = { ElementType.FIELD,ElementType.TYPE,ElementType.METHOD}) @Retention(value = RetentionPolicy.RUNTIME) public @interface FruitName { String value() default ""; }
@Documented @Inherited @Target(value = { ElementType.FIELD}) @Retention(value = RetentionPolicy.RUNTIME) public @interface FruitProvider { public int id() default -1; public String name() default ""; public String address() default ""; }
@Slf4j public class FruitInfoProcessor { private static String fruitName = "水果名:"; private static String fruitColor = "水果颜色:"; private static String fruitProvider = "水果供应商"; public static void printFruitInfo(Class<?> classObj){ Preconditions.checkNotNull(classObj); FruitName fruitName = null; /*读取类的注解*/ fruitName = classObj.getAnnotation(FruitName.class); /*读取service注解*/ Service service = classObj.getAnnotation(Service.class); /*读取所有注解*/ Annotation[] annotations = classObj.getAnnotations(); /*读取方法的注解*/ Method[] methods = classObj.getDeclaredMethods(); for(Method method:methods){ annotations = method.getDeclaredAnnotations(); } Method method = null; try { method = classObj.getDeclaredMethod("getName"); annotations = method.getDeclaredAnnotations(); fruitName = method.getAnnotation(FruitName.class); String value = fruitName.value(); System.out.println("value=" + value); Apple apple = new Apple(); String name = (String) method.invoke(apple); if(Strings.isNullOrEmpty(name)){ name = fruitName.value(); } } catch (NoSuchMethodException e) { log.error("NoSuchMethodException happens!!",e); } catch (IllegalAccessException e) { log.error("IllegalAccessException happens!!",e); } catch (InvocationTargetException e) { log.error("InvocationTargetException happens!!",e); } Field[] fields = classObj.getDeclaredFields(); for(Field field:fields){ fruitName = field.getAnnotation(FruitName.class); if(fruitName != null){ String fruitNameStr = fruitName.value(); System.out.println("\t" + fruitName + fruitNameStr); } FruitColor fruitColor = field.getAnnotation(FruitColor.class); if(fruitColor != null){ FruitColor.Color color = fruitColor.value(); System.out.println("\t" + fruitColor + color); } FruitProvider fruitProvider = field.getAnnotation(FruitProvider.class); if(fruitProvider != null){ int id = fruitProvider.id(); String name = fruitProvider.name(); String address = fruitProvider.address(); System.out.println("id = " + id + ";name = " + name + ";address = " + address); } } } }
五、总结:
java注解是一种标记,这种标记可以赋予程序一些特定的功能,从而在编程时可以减少编码量。java注解主要依靠反射技术实现特定的功能。