一般在平时的编码中,我们很少会用到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; }
我们的本意是希望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了吧。