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);
如果你仍然不知道我( - 。
你在哪裏找到getAnnotations的通用版本?我只能看到getAnotation(class)和getAnnotations()。 – Audrius
哦,我的壞:它不返回一個數組。但它怎麼可能 - 一個類只能有一個同步類型的註解:http://developer.android.com/reference/java/lang/Class.html#getAnnotation(java.lang.Class ) –
這是對的,但這是我遇到的問題。 getAnnotation(Synchronised.class)只返回null。如果我使用getAnnotations()並遍歷它,我可以看到我的註釋,但它看起來像一個動態代理,因此即使比較類也不起作用。 annotation.getClass()。toString()給了我「類Proxy2」,annotation.annotationType()。toString()給了我一個正確的類名。所以我認爲有可能從動態代理檢索我的真實註釋對象,但我不知道如何。 – Audrius