Annotation操作
Annotation操作:减少配置的出现
Annotation的开发与定义在程序中有所支持
- 取得配置的Annotation
在Class AccessibleObject类(java.lang.reflect)里面提供有取得一个结构(构造、方法、成员)的所有Annotation定义
方法:
public Annotation[] getAnnotations()
范例定义一个类:
package com.csii.wanghaoxin.demo;
import java.io.Serializable;
import java.lang.annotation.Annotation;
@Deprecated
@SuppressWarnings("serial")
class Member implements Serializable{
}
public class TestAnnotation {
public static void main(String[] args) {
Class<?> cls = Member.class;
Annotation ant[] = cls.getAnnotations();
for(int i=0;i<ant.length;i++){
System.out.println(ant[i]);
}
}
}
发现只有一个Annotation取得 : @java.lang.Deprecated()
以上只是取得了类的Annotation,方法上也可以取得对应的Annotation
Member.class读取的是class,只是java文件有两个annotation,并没有保存到class中
范例:在方法上定义Annotation
package com.csii.wanghaoxin.demo;
import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
class Member{
@Deprecated
@Override
public String toString(){
return "HELLO";
}
}
public class TestAnnotation {
public static void main(String[] args) throws Exception {
Class<?> cls = Member.class;
Method met = cls.getMethod("toString");
Annotation ant[] = met.getAnnotations();
for(int i=0;i<ant.length;i++){
System.out.println(ant[i]);
}
}
}
声明过期操作是最长久的Annotation.
- 代定义Annotation
以上都是观察了系统的Annotation,但是实际上用户也可以定义属于自己的Annotation。如果要想进行自定义的Annotation,那么必须要明确一个Annotation的运行策略问题。
Enum RetentionPolicy 枚举类型:
RetentionPolicy.CLASS:将Annotation保存在类中,定义的时候生效
RetentionPolicy.RUNTIME:在程序运行的时候生效
RetentionPolicy.SOURCE :在程序源代码定义的时候生效
查看jdk安装目录下的src 源代码包
src.zip\java\lang下的Override.java:
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.SOURCE)
public @interface Override {
}
Target第一个指定@override出现的位置只有方法上。
还有Deprecated.java文件
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(value={CONSTRUCTOR, FIELD, LOCAL_VARIABLE, METHOD, PACKAGE, PARAMETER, TYPE})
public @interface Deprecated {
}
SuppressWarnings.java文件下的:
@Target({TYPE, FIELD, METHOD, PARAMETER, CONSTRUCTOR, LOCAL_VARIABLE})
@Retention(RetentionPolicy.SOURCE)
范例:定义Annotation
新建一个Annotation:
package com.csii.wanghaoxin.annotation;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import com.sun.xml.internal.ws.api.streaming.XMLStreamReaderFactory.Default;
@Retention(RetentionPolicy.RUNTIME)
public @interface MyAnnotation {
public String name() default "wanghaoxin";
public String value();
}
此时没有声明,可以直接在类上进行使用
此时name属性的内容由于存在默认值,所以可以不写,而value()属性没有默认值,所以必须要写上value的内容
package com.csii.wanghaoxin.demo;
import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import com.csii.wanghaoxin.annotation.MyAnnotation;
@MyAnnotation(value = "hello",name="ninhao" )
class Member{
}
public class TestAnnotation {
public static void main(String[] args) throws Exception {
Class<?> cls = Member.class;
Method met = cls.getMethod("toString");
Annotation ant[] = cls.getAnnotations();
for(int i=0;i<ant.length;i++){
System.out.println(ant[i]);//@com.csii.wanghaoxin.annotation.MyAnnotation(name=wanghaoxin, value=hello)
//进行annotation的转换
MyAnnotation ma = (MyAnnotation) ant[i];
System.out.println(ma.name());
System.out.println(ma.value());
}
}
}
以上只是演示了自定义Annotation的操作,但是从本质上来讲,代码不可能这么简单。重在理解原理
- 利用Annotation改善工厂设计
在之前的工厂设计模式之中使用了反射机制以及资源文件,但是资源文件的问题实际上挺麻烦,因为如果资源文件过多,项目本身也不适合维护。
package com.csii.wanghaoxin.demo;
import java.lang.annotation.Annotation;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
interface Fruit{
public void eat();
}
class Apple implements Fruit{
@Override
public void eat() {
System.out.println("吃苹果");
}
}
class Orange implements Fruit{
@Override
public void eat() {
System.out.println("吃橘子");
}
}
@Retention(RetentionPolicy.RUNTIME)
@interface FactoryFlag{//定义一个Annotation
public String className();//定义一个classname属性
}
@FactoryFlag(className="com.csii.wanghaoxin.demo.Apple")
class Factory{
public static Fruit getInstance() throws Exception{
/*return new Apple();*/
//利用反射
//获取annotation的属性值
Annotation ant = Factory.class.getAnnotation(FactoryFlag.class);//取得指定的Annotation
FactoryFlag ff = (FactoryFlag) ant;
return (Fruit)Class.forName(ff.className()).newInstance();
}
}
public class TestFactory {
public static void main(String[] args) throws Exception {
Fruit f = Factory.getInstance();
f.eat();
}
}
它和配置文件相比,各有各的优点和缺点,实际上现在的开发也陷入了纠结的环境,很多人认为写配置文件好,很多人认为写Annotation好。根据具体情况决定。
真正的Annotation开发还需要做一个容器,annotation参数自动维护。代码不关闭。外部自动维护。
- *总结
Annotation能理解就好