2011-02-24 56 views
6

我試圖開發數據庫同步的ORM,並決定給Java反射去。我有一個定義這樣Java自定義註釋和動態加載

@Retention(RetentionPolicy.RUNTIME) 
@Target(ElementType.TYPE) 
@Inherited 
public @interface Synchronised { 
    String tableName(); 
    SynchronisationType synchronisationType(); 
} 

在Android項目我使用此批註標記一個模型類

@Synchronised(tableName="UserAccounts", synchronisationType=SynchronisationType.DownloadOnly) 
public class UserAccount { 
    @SynchronisedField(fieldName="CompanyFk") 
    private int companyId; 
    @SynchronisedField(fieldName="Id") 
    private int userId; 
    @SynchronisedField(fieldName="Username") 
    private String username; 
    @SynchronisedField(fieldName="Password") 
    private String password; 
    @SynchronisedField(fieldName="Salt") 
    private String salt; 
    @SynchronisedField(fieldName="IsLocked") 
    private boolean isLocked; 
    @SynchronisedField(fieldName="HasMobileAccess") 
    private boolean hasMobileAccess; 
} 

一些研究的同步後,註釋庫「裝載」的方法終於被寫入,允許發現在當前的apk模型類。它應該檢索所有標記爲「同步」的類,但問題在於getAttribute(Synchronised.class)不起作用。手動迭代註釋並搜索屬性(instanceof等)也不起作用。在調試時,我注意到來自反射的註釋實際上是一個代理(getClass()給出了「類Proxy2」,而annotation.AnnotationType()返回了正確的名稱) - 這解釋了爲什麼我以前的嘗試不成功。當試圖直接施放時 - 拋出一個強制異常(可以理解)。基本上我在這裏虧本,所以任何想法都歡迎。

模型加載方法(在庫項目):

public static List<Class> getModels(Context context, String packageName) 
     throws IOException, URISyntaxException, ClassNotFoundException, 
      NameNotFoundException { 

     String apkName = context.getPackageManager().getApplicationInfo(packageName, 0).sourceDir; 
     DexFile dexFile = new DexFile(apkName); 
     //PathClassLoader classLoader = new PathClassLoader(apkName, ClassLoader.getSystemClassLoader());  
     PathClassLoader classLoader = new PathClassLoader(apkName, Thread.currentThread().getContextClassLoader()); 

     List<Class> classes = new ArrayList<Class>(); 
     Enumeration<String> entries = dexFile.entries(); 

     while (entries.hasMoreElements()) { 

      String entry = entries.nextElement(); 
      // only check items that exist in source package and not in libraries, etc. 
      if (entry.startsWith(packageName)) { 
       Log.d(TAG, "Entry: " + entry); 

       Class<?> entryClass = classLoader.loadClass(entry);//dexFile.loadClass(entry, classLoader); 
       if (entryClass != null) { 
        Annotation[] annotations = entryClass.getAnnotations(); 
        for (Annotation annotation : annotations) { 
         if (annotation instanceof Synchronised) { 
          classes.add(entryClass); 
         } 
        } 
       } 
      }    
     } 

     return classes;  
    } 

[方案]類加載器需要被捆綁,像這樣:

PathClassLoader classLoader2 = new PathClassLoader(apkName, Thread.currentThread().getContextClassLoader()); 
DexClassLoader classLoader = new DexClassLoader(apkName, new ContextWrapper(context).getCacheDir().getAbsolutePath(), null, classLoader2); 

如果你仍然不知道我( - 。

回答

2

只需注下您感興趣的內容:

Annotation<Synchronised> annotation = entryClass.getAnnotation(Synchronised.class); 

更新:

的問題是,DexFile.getClass()返回顯然的代理。 OP找到了問題並用解決方案更新了問題。