JavaWeb的配置信息,以前是使用配置xml文件来做,所以会有很多的配置,这样会很不方便。所以在Servlet3.0后提供了注解的方式来达到配置的目的。
1. 注解定义
注解的使用我们看到很多,形如 @WebServlet(...) 这种。一个注解的定义如下
package test.annotation;
// 这里定义一个 Action 注解
public @interface Action {
}
2. 元注解
元注解就是注解的注解,在注解的定义中,我们还可以对定义的注解进行注解。
package test.anntation;
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface Action {
}
这里的 @Target , @Retention 就是元注解。
@Retention 注解
它是被定义在一个注解类的前面,用来说明该注解的生命周期。它有以下参数:
RetentionPolicy.SOURCE :指定注解只保留在一个源文件当中。
RetentionPolicy.CLASS :指定注解只保留在一个 class 文件中。
RetentionPolicy.RUNTIME :指定注解可以保留在程序运行期间。
@Target 注解
它是被定义在一个注解类的前面,用来说明该注解可以被声明在哪些元素前面。它有以下参数:
ElementType.TYPE :说明该注解只能被声明在一个类前。
ElementType.FIELD :说明该注解只能被声明在一个类的字段前。
ElementType.METHOD :说明该注解只能被声明在一个类的方法前。
ElementType.PARAMETER :说明该注解只能被声明在一个方法参数前。
ElementType.CONSTRUCTOR :说明该注解只能声明在一个类的构造方法前 。
ElementType.LOCAL_VARIABLE :说明该注解只能声明在一个局部变量前。
ElementType.ANNOTATION_TYPE :说明该注解只能声明在一个注解类型前 。
ElementType.PACKAGE :说明该注解只能声明在一个包名前。
如果不加该注解表示可以声明在任何位置
3. 参考
4. 测试
4.1 @Override
package test.override;
class A {
public void print() {
System.out.println("A");
}
}
class B extends A {
public void print() {
System.out.println("B");
}
}
public class OverrideTest {
public static void main(String[] args) {
A a = (A) new B();
a.print();
}
}
// output
B
如果在类 B的 print 方法上加上 @Override,表示这个 print 方法是重写父类 A 的 print 方法,如果不加这个的话,如果 B 的意思是重写 A 的方法 print,但是在B的实现中写成了 Print,这时如果没有 @Override 注解,那么程序是不会报错的,如果你粗心的话,这样就发现不了,但是加上了 @Override, 如果检查到 B 中的方法不是重写父类的方法,那么编译通过不了。估计这就是 @Override 的作用了。
4.2 自定义注解使用
// Action.java
package test.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target(ElementType.TYPE) // 这个意思是这个注解只能在类的开始,在类的内部使用会出错
@Retention(RetentionPolicy.RUNTIME)
public @interface Action {
}
// AnnotationTest.java
package test.annotation;
@Action
class ActionAnnotation {
}
public class AnnotationTest {
public static void main(String[] args) {
System.out.println(ActionAnnotation.class.isAnnotationPresent(Action.class)); // 判断ActionAnnotation这个类是否使用到了 Action 注解
System.out.println(ActionAnnotation.class.isAnnotation());
System.out.println(Action.class.isAnnotation());
}
}
/*
// output
true
false
true
*/
代码片段2
// Action.java
package test.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target(ElementType.TYPE) // 定义Action注解只能在类的开始
@Retention(RetentionPolicy.RUNTIME) // 载入到JVM中的代码片段,包括注解信息
public @interface Action {
}
// RequestBean.java
package test.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target(ElementType.METHOD) // 定义RequestBean注解在方法上
@Retention(RetentionPolicy.RUNTIME)
public @interface RequestBean {
/*
注解中再定义注解
*/
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Get {
String value();
}
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Post{
String value();
}
}
// AnnotationTest.java
package test.annotation;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
@Action
class ActionAnnotation {
@RequestBean.Get("/hello")
public void doGetTest(String info) {
System.out.println("Get: " + info);
}
@RequestBean.Post("/hello")
public void doPostTest(String info) {
System.out.println("Post: " + info);
}
}
public class AnnotationTest {
public static void main(String[] args)
throws
IllegalAccessException,
IllegalArgumentException,
InvocationTargetException,
InstantiationException,
ClassNotFoundException {
// 获得ActionAnnotation类的对象实例
Object obj = Class.forName("test.annotation.ActionAnnotation").newInstance();
// 获得ActionAnnotation类中的方法
Method[] methods = ActionAnnotation.class.getDeclaredMethods();
// 遍历获得的方法
for(Method method : methods) {
// 如果这个方法上的注解为 RequestBean.Get
if(method.isAnnotationPresent(RequestBean.Get.class)) {
String info = method.getAnnotation(RequestBean.Get.class).value();
// 调用该注解标识的方法
method.invoke(obj, info);
} else if(method.isAnnotationPresent(RequestBean.Post.class)) {
String info = method.getAnnotation(RequestBean.Post.class).value();
method.invoke(obj, info);
}
}
}
}
// output
Post: /hello
Get: /hello