一、Annotation简介
从Java5.0版发布以来,5.0平台提供了一个正式的annotation功能:允许开发者定义、 用自己的annotation类型。此功能由一个定义annotation类型的语法和一个描述annotation声明的语法,读取annotation的API,一个使用annotation修饰的class文件,一个annotation处理工具(apt)组成。
annotation并不直接影响代码语义,但是它能够以工作的方式被看作类似程序的工具或者类库,它会反过来对正在运行的程序语义有所影响。annotation可以从源文件、class文件或者以在运行时反射的多种方式被读取。Annotation用到的地方非常普遍。
二、Annotation在应用中的小例子
用户有不同的角色,不同角色有不同的权限,不同权限的用户登录进来能看到的数据也不同,能操作的功能不同。
请看代码示例
package com.cienet.authority;
public class User {
private Integer userId;
private String name;
private RoleEnum role;
public User(Integer userId, String name, RoleEnum role) {
super();
this.userId = userId;
this.name = name;
this.role = role;
}
public Integer getUserId() {
return userId;
}
public void setUserId(Integer userId) {
this.userId = userId;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public RoleEnum getRole() {
return role;
}
public void setRole(RoleEnum role) {
this.role = role;
}
}
package com.cienet.authority;
public enum RoleEnum {
ProjectManager, Developer;
}
package com.cienet.authority;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@Retention(RetentionPolicy.RUNTIME)
public @interface AuthorityAnnotation {
RoleEnum[] value();
}
package com.cienet.authority;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;
public class Action {
private Map<String, User> session = new HashMap<String, User>();
public String login() throws Exception {
System.out.println(session.get("user").getName() + " ---- 執行注册操作:");
String invoke = "login";
// 1. check privilage
checkUser(session.get("user"), invoke);
// 2. do business
System.out.println("恭喜您,注册成功!\n");
return "success";
}
@AuthorityAnnotation( {RoleEnum.ProjectManager, RoleEnum.Developer})
public String queryUser() throws Exception {
System.out.println(session.get("user").getName() + " ----- 執行查询操作:");
String invoke = "queryUser";
// 1. check privilage
checkUser(session.get("user"), invoke);
// 2. do business
System.out.println("查询操作成功!\n");
return "success";
}
@AuthorityAnnotation(RoleEnum.ProjectManager)
public String deleteUser() throws Exception {
System.out.println(session.get("user").getName() + " ----- 執行删除操作:");
String invoke = "deleteUser";
checkUser(session.get("user"), invoke);
System.out.println("删除操作成功!\n");
return "success";
}
/**
* this method replace interceptor of struts2
*
* @param loginUser
* @param invoke
* @return
* @throws Exception
*/
private void checkUser(User loginUser, String invoke) throws Exception {
Class action = this.getClass();
Method method = action.getMethod(invoke, new Class[] {});
boolean authFlag = false;
if (method.isAnnotationPresent(AuthorityAnnotation.class)) {
AuthorityAnnotation annotation = method
.getAnnotation(AuthorityAnnotation.class);
RoleEnum[] role = annotation.value();
for (int i = 0; i < role.length; i++) {
if (loginUser.getRole() == role[i]) {
authFlag = true;
break;
}
}
} else {
authFlag = true;
}
if (!authFlag) {
throw new RuntimeException("哥们,你权限不足,走人!\n");
}
}
public Map<String, User> getSession() {
return session;
}
}
package com.cienet.authority;
import java.util.HashMap;
import java.util.Map;
public class Client {
public static void main(String[] args) throws Exception {
Action action = new Action();
User projectManager = new User(1, "孙悟空", RoleEnum.ProjectManager);
action.getSession().put("user", projectManager);
User developer = new User(2, "牛魔王", RoleEnum.Developer);
action.getSession().put("user", developer);
User other = new User(3, "西门催雪", null);
action.getSession().put("user", other);
action.login();
action.queryUser();
action.deleteUser();
}
}
三、使用JDK5内建Annotation
@Override
该注解只能用在方法上,表示被注解的方法重写了父类的方法。
@Deprecated
被注解的元素不建议被使用。
@SuppressWarnings
该注解告诉编译器压制指定的警告信息。
参见程序实例
package com.cienet.internal;
class Person {
public String getInfo() {
return "this is person";
}
}
public class OverrideTest extends Person {
@Override
public String getInfo() {
return "this is student";
}
public static void main(String[] args) {
Person person = new OverrideTest();
System.out.println(person.getInfo());
}
}
package com.cienet.internal;
import java.util.Date;
public class DeprecatedTest {
@Deprecated
public String doSomething() {
return "doSomething";
}
public static void main(String[] args) {
DeprecatedTest deprecatedTest = new DeprecatedTest();
System.out.println(deprecatedTest.doSomething());
}
}
package com.cienet.internal;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
public class SuppressWarningsTest {
//@SuppressWarnings("unchecked")
public static void main(String[] args) {
Map map = new HashMap();
//Map<String, Date> map = new HashMap<String,Date>();
map.put("hello", new Date());
System.out.println(map.get("hello"));
DeprecatedTest test = new DeprecatedTest();
test.doSomething();
}
}
java.lang.Override是个Marker annotation
java.lang.Deprecated也是個Marker annotation
-
l deprecation 使用了过时的类或方法时的警告
-
l unchecked 执行了未检查的转换时的警告,例如当使用集合时没有用泛型 (Generics) 来指定集合保存的类型
-
l fallthrough 当 Switch 程序块直接通往下一种情况而没有 Break 时的警告
-
l path 在类路径、源文件路径等中有不存在的路径时的警告
-
l serial 当在可序列化的类上缺少 serialVersionUID 定义时的警告
-
l finally 任何 finally 子句不能正常完成时的警告
-
l all 关于以上所有情况的警告
四、自定义Annotation类型
定义Marker Annotation,也就是Annotation名称本身即提供信息
对于程序分析工具来说,主要是检查是否有MarkerAnnotation的出现,并作出对应的动作
使用@interface自行定义Annotation型态时,实际上是自动继承了java.lang.annotation.Annotation接口
由编译程序自动为您完成其它产生的细节
在定义Annotation型态时,不能继承其它的Annotation型态或是接口
参见程序实例
package com.cienet.define;
public enum EnumTest {
Hello,World,Welcome;
}
package com.cienet.define;
public interface MyAnnotation {
}
package com.cienet.define;
//@MyAnnotation
public class AnnotationUsage {
public void method() {
System.out.println("usage of annotation");
}
public static void main(String[] args) {
AnnotationUsage annotationUsage = new AnnotationUsage();
annotationUsage.method();
}
}
Annotation里定义的类型必须为以下的类型及其数组:
1. 八种原始数据类型
2. String
3. Class
4. Enum
5.Annotation