`
lg_asus
  • 浏览: 184319 次
  • 性别: Icon_minigender_1
  • 来自: 苏州
社区版块
存档分类
最新评论

Thinking In Java 4th 关于Annotation处理器的观察者模式

 
阅读更多
首先先定义SQLString SQLInteger Constraints这三个Annotation,下面以SQLString为代表:
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface SQLString {
	public int length() default 0;
	String name() default "";
	Constraints constraints() default @Constraints(allowNull=true);
}


然后定义AnnotationProcessor 和 AnnotationProcessorFactory, 注意内部类和观察者模式在这里的运用:
public class TableCreationProcessorFactory implements AnnotationProcessorFactory{
	
	@Override
	public AnnotationProcessor getProcessorFor(
			Set<AnnotationTypeDeclaration> atds,
			AnnotationProcessorEnvironment env) {
		return new TableCreationProcessor(env);
	}

	@Override
	public Collection<String> supportedAnnotationTypes() {
		return Arrays.asList("annotations.database2.DBTable", "annotations.database2.Constraints", "annotations.database2.SQLString", "annotations.database2.SQLInteger");
	}

	@Override
	public Collection<String> supportedOptions() {
		return Collections.emptyList();
	}
	
	private class TableCreationProcessor implements AnnotationProcessor{
		public TableCreationProcessor(AnnotationProcessorEnvironment env) {
			this.env = env;
		}

		private final AnnotationProcessorEnvironment env;
		private String sql = "";
		
		@Override
		public void process() {
			for(TypeDeclaration typeDec : this.env.getTypeDeclarations()){
				typeDec.accept(DeclarationVisitors.getDeclarationScanner(new TableCreationVisitor(), DeclarationVisitors.NO_OP));
				sql = sql.substring(0, sql.length()-1)+");";
				System.out.println("creation SQL is : "+sql);
				sql = "";
			}
		}
		
		private class TableCreationVisitor extends SimpleDeclarationVisitor{

			@Override
			public void visitClassDeclaration(ClassDeclaration d) {
				DBTable dbTable = d.getAnnotation(DBTable.class);
				if(dbTable != null){
					sql +="CREATE TABLE ";
					sql += (dbTable.name().length() < 1) ? d.getSimpleName().toUpperCase() : dbTable.name();
					sql += " (";
				}
			}
			
			@Override
			public void visitFieldDeclaration(
					FieldDeclaration d) {
				if(d.getAnnotation(SQLString.class) != null){
					System.out.println("process SQLString");
					SQLString sqlString = d.getAnnotation(SQLString.class);
					sql += (sqlString.name().equals("")? d.getSimpleName().toUpperCase():sqlString.name())+" varchar2("+sqlString.length()+")"
							+getConstraints(sqlString.constraints())+",";
				}else if(d.getAnnotation(SQLInteger.class) != null){
					System.out.println("process SQLInteger");
					SQLInteger sqlInteger = d.getAnnotation(SQLInteger.class);
					sql += (sqlInteger.name().equals("")?d.getSimpleName().toUpperCase():sqlInteger.name())+" INT" +",";
				}
			}
			
			private String getConstraints(Constraints c){
				String temp = "";
				if(c.primaryKey()){
					temp += " PRIMARY KEY";
				}
				if(!c.allowNull()){
					temp += " NOT NULL";
				}
				if(c.unique()){
					temp += " UNIQUE";
				}
				return temp;
			}
		}
	}
}


在书中,getDeclarationScanner这是DeclarationVisitors中的静态方法,作者直接引用,由于我没看import的习惯,害我找了半天,我不推荐直接引用静态方法和变量。
getDeclarationScanner中两个参数分别表示:访问每个声明前使用的Visitor,访问每个声明后的Visitor,这里只需要访问前的Visitor,因此第二个参数用DeclarationVisitors.NO_OP表示什么也不做,这里不能直接new TableCreationVisitor()作为TypeDeclaration.accept的参数,否则只有visitClassDeclaration()这个方法被调用,visitFieldDeclaration()竟然不被调用,很奇怪。SupportedType指明哪些Annotation需要处理,supportedOperation不知道什么作用。
下面是测试代码:
public class Test {

	public static void main(String...args){
		try{
			Process p = Runtime.getRuntime().exec("cmd /c apt -factory annotations.database2.TableCreationProcessorFactory annotations/database2/Member.java");
			final BufferedReader input = new BufferedReader(new InputStreamReader(p.getInputStream(),"gb2312"));//解决中文乱码
			final BufferedReader error = new BufferedReader(new InputStreamReader(p.getErrorStream(),"gb2312"));
			new Thread(){
				String str = null;
				@Override
				public void run() {
					try {
						while((str = input.readLine())!=null){
							System.out.println(str);
						}
					} catch (IOException e) {
						e.printStackTrace();
					}
				}
				
			}.start();
			new Thread(){
				String str = null;
				@Override
				public void run() {
					try {
						while((str = error.readLine())!=null){
							System.out.println("Err: "+str);
						}
					} catch (IOException e) {
						e.printStackTrace();
					}
				}
				
			}.start();
			System.out.println("exit: "+p.waitFor());
		}catch(IOException e){
			e.printStackTrace();
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
	}
}


运行结果:
CREATE TABLE member (FIRSTNAME varchar2(30),LASTNAME varchar2(50),AGE INT,HANDLE varchar2(30) PRIMARY KEY);
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics