java annotation+反射的應用記錄

使用java 的annotation和反射的小例子,記錄下來以供參考,java

實現的功能是 配置頁面能夠動態選擇一個實現檢核接口的類,保存輸入的參數,在真正檢核時傳入保存的參數web

配置頁面以下:第一行選擇了檢核1 有三個參數須要輸入,第二行能夠看到下拉選單,內容是根據annotation標註的class生成的spring

 

下拉選單是根據annotation標註的class生成的,目前是有3個測試class,選擇了之後能夠填入須要的參數進行保存,參數也是定義在class中,目前先講一講這部分配置的實現。ide

  自定義一個annotation測試

1 @Retention(RetentionPolicy.RUNTIME) 2 @Target(ElementType.TYPE) 3 public @interface AnnotBpbAssertionClass { 4 
5     public String descr() default ""; 6 }

其中一個檢核class,實現的接口是爲了實做assertData方法,檢核調用的真正方法,ui

@AnnotBpbAssertionArg標註輸入的參數,能夠看到和上面頁面上的匹配
 1 @AnnotBpbAssertionClass(descr="檢核1")  2 public class TestAssert1 implements AssertionClassHandler{  3 
 4  @AnnotBpbAssertionArg  5     private String arg1;  6  @AnnotBpbAssertionArg  7     private String arg2;  8  @AnnotBpbAssertionArg  9     private String arg3; 10     public String getArg1() { 11         return arg1; 12  } 13     public void setArg1(String arg1) { 14         this.arg1 = arg1; 15  } 16     public String getArg2() { 17         return arg2; 18  } 19     public void setArg2(String arg2) { 20         this.arg2 = arg2; 21  } 22     public String getArg3() { 23         return arg3; 24  } 25     public void setArg3(String arg3) { 26         this.arg3 = arg3; 27  } 28  @Override 29     public AssertionResult assertData() { 30      
31  } 32  
33     
34 }

 

  爲了效率比較高,標註有annotation的class是在spring加載bean的時候寫入內存的,service須要實現InitializingBean,初始化方法中用到了類掃描this

首先得到Reflections,PKG_NAME 爲掃描其實包路徑,若是以爲沒有用也能夠在調用時抓取一次spa

 

 1  private static Reflections getRef(String pkgName) {  2         String sPkgName = pkgName == null ? PKG_NAME : pkgName;  3 
 4         Set<URL> clzLoaderUrls = ClasspathHelper.forPackage(sPkgName);  5         Set<URL> webInfoLibUrls = Collections.emptySet();  6         Set<URL> scanUrls = new LinkedHashSet<URL>();  7 
 8         try {  9             ServletContext servletContext = WebContextInfo.getInstance().getParentServletContext(); 10             webInfoLibUrls = ClasspathHelper.forWebInfLib(servletContext); 11             URL webInfoClassUrls = ClasspathHelper.forWebInfClasses(servletContext); 12             if(webInfoClassUrls != null){ 13  scanUrls.add(webInfoClassUrls); 14  } 15         } catch (Exception e) { 16             LG.warn(ClassScanner.class.getSimpleName(), 17                     "get webinf lib/class failed., err: {0}", e.getMessage()); 18  } 19 
20  scanUrls.addAll(webInfoLibUrls); 21  scanUrls.addAll(clzLoaderUrls); 22 
23         ConfigurationBuilder cfgBuilder = new ConfigurationBuilder(); 24         cfgBuilder.filterInputsBy(new FilterBuilder.Include(FilterBuilder.prefix(sPkgName))); 25  cfgBuilder.addScanners( 26                 new SubTypesScanner(), 27                 new TypeAnnotationsScanner(), 28                 new MethodAnnotationsScanner(), 29                 new FieldAnnotationsScanner()); 30  cfgBuilder.setUrls(scanUrls); 31 
32         Reflections refs = new Reflections(cfgBuilder); 33         return refs; 34     }

得到全部標註annotation的class集合。code

        Reflections ref = getRef(); Set<Class<?>> ret = ref.getTypesAnnotatedWith(annotation);   

將class和annotation的信息封裝在 BpbAssertionClassMeta 這個類中,能夠看到class和annotation的一些方法。orm

 

      if (CollectionUtils.isNotEmpty(clazzSet)) { for (Class<?> clazz : clazzSet) { BpbAssertionClassMeta meta = new BpbAssertionClassMeta(); List<ArgMeta> argMetas = new ArrayList<BpbAssertionClassMeta.ArgMeta>(); meta.setArgs(argMetas); meta.setClassName(clazz.getCanonicalName()); AnnotBpbAssertionClass annotation = clazz.getAnnotation(AnnotBpbAssertionClass.class);//獲取annotation meta.setDesc(annotation.descr()); metas.add(meta); Field[] declaredFields = clazz.getDeclaredFields();//獲取類的全部字段 if (declaredFields != null) { for (Field field : declaredFields) { if (field.isAnnotationPresent(AnnotBpbAssertionArg.class)) {//是否標註的此annotation if (String.class.isAssignableFrom(field.getType()) == false) {//是否string類型 throw new IllegalArgumentException( String.format( "unsupported type!, expected %s but %s found. @field: %s, @class: %s", String.class.getSimpleName(), field.getType() .getSimpleName(), field.getName(), clazz .getName())); } ArgMeta argMeta = meta.new ArgMeta(); argMeta.setField(field); argMeta.setDesc(field.getName()); argMetas.add(argMeta); } } } } }

頁面循環BpbAssertionClassMeta  就能夠渲染此頁面了。

相關文章
相關標籤/搜索