Java之注解

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. 参考

http://my.oschina.net/aiguozhe/blog/59661

http://blog.csdn.net/jiangwei0910410003/article/details/18501195

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

你可能感兴趣的:(java,注解)