一般在平时的编码中,我们很少会用到annotation,而一些java框架渐渐开始使用annotation来使框架的配置、开发更趋简洁和方便。之前总是很奇怪到底在annotation中做了些什么 事情,可以实现这么有趣的功能。一起想了解一下,由于工作中实在很少会用到,因此才搁置到今天,来学习一下annotation的使用,仅写一些自己实践的代码,并没有深入地去详解其中的原理。
新建一个annotation类
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface InitString {
String value();
}
这里有几部份内容:
第一部分:Retention设置,其本身也是一个annotation类,主要用于指定该annotation的可见范围。后面跟的RetentionPolicy有三个值:source-只在源文件中出现,不会编译后加到类文件中,更不可能在运行时获取到;class-默认值,编译后会添加到类文件中,但是不能在运行时获取到,打开后面介绍的使用类的文件可以看到,这个annotation是RuntimeInvisibleAnnotations的;runtime-表明该annotation可以在运行时获取到,打开后面介绍的使用类的文件 可以看到是RuntimeVisibleAnnotations的。
第二部分:Target设置,与Retention一样,也是annotation类,主要用于指定该annotation的作用对象。可以有TYPE、FIELD、METHOD、PARAMETER、CONSTRUCTOR、LOCAL_VARIABLE、ANNOTATION_TYPE、PACKAGE,从其命名就可以大致明白其作用对象了。
第三部分:annotation类的主体申明,你可以添加其成员变更,如上例中的value(),以在后续的使用中指定该值。
定义好上面的类之后,接下来是使用,首先是在某个类中添加annotation:
public class SomeClass {
@InitString("hello world!")
public String strField;
}
由于该annotation是作用于属性上的,所以将其加到属性strField上,并且指定其自身的属性value的值,如果该属性名不是value,则需要写成@InitString(XXX="hello world!"),其中XXX为属性名。
我们的本意是希望SomeClass的strField属性能够自动初始为"hello world!",那么如果做到这个效果呢?其实这个就不再是annotation类的职责了,而是需要我们自己在类初始化或者使用时,去通过反射取到annotation信息,然后做相应的操作,如:
public class MainTest {
/**
* @param args
* @throws IllegalAccessException
* @throws IllegalArgumentException
*/
public static void main(String[] args) throws IllegalArgumentException,
IllegalAccessException {
SomeClass sc = new SomeClass();
for (Field m : sc.getClass().getDeclaredFields()) {
if (m.isAnnotationPresent(InitString.class)) {
// 如果没有访问权限,则设置访问权限
if (!m.isAccessible()) {
m.setAccessible(true);
}
m.set(sc, m.getAnnotation(InitString.class).value());
}
}
System.out.println(sc.strField);
}
}
最终的输出结果:
hello world!
通过这样的方法,我们就可以使用annotation来初始化,所以大家应该可以理解spring这些框架如何通过annotation来注入bean了吧。