咱們實現一個完整的一個例子,那麼基本瞭解了其運行機制。
java
1 建立一個處理註解的項目框架
依次爲一個註解,一個註解處理器,一個註解路徑配置文件(供編譯器識別)。ide
註解Seriable代碼:測試
@Target({ ElementType.FIELD, ElementType.TYPE }) @Retention(RetentionPolicy.CLASS) public @interface Seriable { }
@Retention標明生命週期,this
RetentionPolicy.CLASS //表示註解是在編譯期處理
這個配置文件的內容是BeanProcessor.java的完整路徑:com.zhy.annotationprocess.processor.BeanProcessor.spa
這個BeanProcessor.java的代碼爲:code
@SupportedSourceVersion(SourceVersion.RELEASE_6) public class BeanProcessor extends AbstractProcessor { // 元素操做的輔助類 Elements elementUtils; ProcessingEnvironment processingEnv; @Override public synchronized void init(ProcessingEnvironment processingEnv) { super.init(processingEnv); // 元素操做的輔助類 elementUtils = processingEnv.getElementUtils(); this.processingEnv = processingEnv; } @Override public Set<String> getSupportedAnnotationTypes() { Set<String> typeSet = new LinkedHashSet<String>(); typeSet.add(Seriable.class.getCanonicalName()); return typeSet; } @SuppressWarnings("resource") @Override public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) { processingEnv.getMessager().printMessage(Kind.ERROR, "12346789"); // 得到被該註解聲明的元素 Set<? extends Element> elememts = roundEnv .getElementsAnnotatedWith(Seriable.class); TypeElement classElement = null;// 聲明類元素 List<VariableElement> fields = null;// 聲明一個存放成員變量的列表 // 存放兩者 Map<String, List<VariableElement>> maps = new HashMap<String, List<VariableElement>>(); try { // 遍歷 File file = new File("f:/test.txt"); FileWriter fWriter = null; fWriter = new FileWriter(file,true); FileOutputStream outputStream = new FileOutputStream(file,true); outputStream.write((" ======elememts size : " +elememts.size()+ "\n").getBytes()); int i = 1; for (Element ele : elememts) { //processingEnv.getMessager().printMessage(Kind.ERROR, "12346789",ele); outputStream.write((" ======start\n").getBytes()); outputStream.write((" element name:" + ele.getSimpleName() + " index:" + i + "\n").getBytes()); outputStream.write((" element enclose_name:"+ele.getEnclosingElement().getSimpleName()+"\n").getBytes()); outputStream.write(( "element kind:" + ele.getKind().name() + "\n").getBytes()); outputStream.write(( " element type:" + ele.asType().getKind().name() + "\n").getBytes()); outputStream.write(("========end\n").getBytes()); i++; } outputStream.flush(); outputStream.close(); } catch (IOException e) { e.printStackTrace(); } return true; } }
而後將其打成一個jar。three
2 建立一個測試簡單註解框架的項目生命週期
percent_1.jar就是剛纔打的jar包element
Article.java和User.java的代碼分別爲:
@Seriable public class Article { private String title ; private String content ; } public class User { @Seriable int username123; @Seriable String password123; private String three; private String four; }
對AnntotaionTest1項目配置,使編譯器能識別jar中的註解處理器BeanProcessor。
配置完以後回頭看BeanProcessor,編譯器識別它以後,會調用它的process(...)入口,根據代碼會在F盤建立一個test.txt文件,裏面打印了被註解的元素的信息。如今咱們來看一下這個文件的內容:
======elememts size : 3
======start
element name:username123 index:1
element enclose_name:User
element kind:FIELD
element type:INT
========end
======start
element name:Article index:2
element enclose_name:com
element kind:CLASS
element type:DECLARED
========end
======start
element name:password123 index:3
element enclose_name:User
element kind:FIELD
element type:DECLARED
========end
======elememts size : 0
果真打印出了3條註解元素的信息,這和咱們在User和Article註解的元素一一對應。
這裏解釋一下:element name的值意思爲註解元素的名稱,element enclose_name:是封裝這個元素的實體名稱,element kind的值被註解元素的角色,字段或者類等其餘,element type:的值表示被註解元素的類型,username123被定義成int,它的type就爲INT,password123被定義成String,它的type就爲DECLARED。至此簡單的編譯註解完成測試。在寫註解處理器的時候有一點要注意,就是必須實現getSupportedAnnotationTypes()方法