7.注解的出现,可以替代某些现有的系统。例如:XDolect,它是一个独立的文档化工具,专门用来生成类似注解一样的文件。
package Unit20注解.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
*
*@Test的定义就像一个接口,@interface注解其实就是一个特殊的接口,在编译成class后也会生成class文件。
*定义接口时,需要一些元注解(meta-annotation),如@Target和@Retention
*
*@Target:用来定义注解用于什么地方,(例如用于一个类,还是一个方法,一个域)
* ElementType包括以下几种:
* 1.CONSTRUCTOR : 构造器的声明。
* 2.FIELD:域声明(包括enum实例)
* 3.LOCAL_VARIABLE:局部变量声明。
* 4.METHOD:方法声明
* 5.PACKAGE:包声明
* 6.PARANETER:参数声明
* 7.TYPE:类,接口(包括注解类型)或enum声明
*
*@Retention:用来定义注解在哪一个级别可以用(在源代码中(SOURCE),类文件中(CLASS),或者运行时(RUNTIME))
*
*@Documented 将此注解包含在Javadoc中。
*
*@Inherited 允许类继承父类中的注解。
*
*注解的元素就像接口中的方法,唯一的区别就是你可以为其指定默认值。
*
*没有元素的注解称为标记注解(Marker annotation)
*/
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Test{
}
package Unit20注解.annotation;
/**
一下的代码,使用@Test对TestExecute()方法进行注解。该注解本
身不做任何事情,但是该注解确保在其构建路径上必须有@Test的注解的定义
*/
public class Testable {
public void execute(){
System.out.println("Executing ...");
}
@Test void testExecute(){execute();};
}
package Unit20注解.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
*
* 下面是一个简单的注解,我们可以用它,跟踪项目中的用例。如果一个方法或是一组方法实现了某
* 个用例的需求,那么程序员可以为该方法加上改注解。于是,项目经理通过计算已经实现的用例,就可以很好的掌握项目的进展。
* 而如果要更新或维护系统的业务逻辑,则维护改项目的开发人员也可以很容易的在代码中找到对应的用例。
*
*/
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface UseCase {//使用:@UseCase(id = 10,description = "这是一个例子")
//以下是参数定义
/*
* 注解的元素只可以使用以下几种类型:
* 1.所有基本类型
* 2.String
* 3.Class
* 4.enum
* 5.Annotation
* 6.以上类型的数组
*
* 如果你使用过了其他类型,那编译器就会报错。注意,也不允许使用任何其他包装类型,注解作为元素的类型,也就是说
* 注解可以嵌套。
*
* */
public int id();
public String description() default "no description";//和接口唯一的区别,可以有默认值
}
package Unit20注解.annotation;
import java.util.List;
public class PasswordUtils {
@UseCase(id = 47 ,description = "Password must contain at least ine numeric")
public boolean validatePassword(String password){//验证密码是否合法
return (password.matches("\\w*\\d\\w*"));
}
@UseCase(id = 48)
public String encryptPassword(String password){//密码加密
return new StringBuilder(password).reverse().toString();
}
@UseCase(id = 49 , description = "New password can't equal previously used ones")
public boolean checkForNewPassword(//
List prevPassword , String password){
return !prevPassword.contains(password);
}
}
package Unit20注解.annotation;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public class UseCaseTracker {//注解处理器
public static void trackUserCases(
List useCases , Class> cl){
for(Method m : cl.getDeclaredMethods()){//getDeclaredMethods可以反射所有方法,包括私有
UseCase uc = m.getAnnotation(UseCase.class);//获取该方法上的UseCase注解
if(uc!=null){
System.out.println("Found Use Case : " + uc.id()+" "
+uc.description());
useCases.remove(new Integer(uc.id()));
}
}
for(int i : useCases)
System.out.println("Warning : Missing use case -"+i);
}
public static void main(String[] args){
List useCases = new ArrayList();
Collections.addAll(useCases, 47,48,49,50);
trackUserCases(useCases, PasswordUtils.class);
}
}
以下是通过注解,来创建数据库表。
package Unit20注解.annotation.DB;
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 DBtable {
public String name() default "";
}
package Unit20注解.annotation.DB;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface SQLInteger {//
String name() default "";
Constraints constraints() default @Constraints;
}
package Unit20注解.annotation.DB;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface SQLString {
int value() default 0;
String name() default "";
Constraints constraints() default @Constraints;//注解嵌套
}
package Unit20注解.annotation.DB;
public @interface Uniqueness {
Constraints constraints()
default @Constraints(unique = true);
}
package Unit20注解.annotation.DB;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Constraints {//主键的注解
boolean primaryKey() default false;
boolean allowNull() default true;
boolean unique() default false;
}
package Unit20注解.annotation.DB;
@DBtable(name = "MEMBER")
public class Member {
@SQLString(30) String firstName;
@SQLString(50) String lastName;
@SQLInteger Integer age;
@SQLString (value = 30 , constraints = @Constraints(primaryKey = true))
String handle;
static int memberCount;
public String getHandle(){return handle;}
public String getFirstName(){return firstName;}
public String getLastName(){return lastName;}
public Integer getAge(){return age;}
public String toString(){return handle;}
}
package Unit20注解.annotation.DB;
import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.List;
public class TableCreator {
public static void main(String[] args) throws Exception{
//System.out.println(System);
args= new String[]{"Unit20注解.annotation.DB.Member"};
//Class.forName(args[0]);
if(args.length < 1){
System.out.println("arguments : annotated classes");
System.exit(0);
}
for(String className : args){
Class> cl = Class.forName(className);
DBtable dbTable = cl.getAnnotation(DBtable.class);
if(dbTable == null){
System.out.println(
"No DBTable annotations in class "+ className);
continue;
}
String tableName = dbTable.name();
//if the name is empty , use the class name
if(tableName.length() < 1){
tableName = cl.getName().toUpperCase();
}
List columnDefs = new ArrayList();
for(Field field : cl.getDeclaredFields()){
String columnName = null;
Annotation[] anns = field.getDeclaredAnnotations();
if(anns.length < 1){
continue;
}
if(anns[0] instanceof SQLInteger){
SQLInteger sInt = (SQLInteger) anns[0];
//Use field name , if naem not specified
if(sInt.name().length() < 1)
columnName = field.getName().toUpperCase();
else
columnName = sInt.name();
columnDefs.add(columnName+ " INT"+
getConstraints(sInt.constraints()));
}
if(anns[0] instanceof SQLString){
SQLString sString = (SQLString) anns[0];
//Use field name if name not specified
if(sString.name().length() < 1){
columnName = field.getName().toUpperCase();
}
else{
columnName = sString.name();
}
columnDefs.add(columnName + " VARCHAR("
+sString.value() + ") "+getConstraints(sString.constraints()));
}
StringBuilder createCommand = new StringBuilder(
"CREATE TABLE "+tableName +" (");
for(String columnDef : columnDefs){
createCommand.append("\n "+columnDef+",");
}
//remove trailing comma
String tableCreate = createCommand.substring(0 , createCommand.length()-1)+");";
System.out.println("Table Creation SQL for "+
className + " is : \n"+ tableCreate);
}
}
}
private static String getConstraints(Constraints con){
String constraints = "";
if(!con.allowNull())
constraints += " NOT NULL ";
if(con.primaryKey())
constraints +=" PRIMARY KEY ";
if(con.unique())
constraints += " UNIQUE ";
return constraints;
}
}