gpt4 book ai didi

Java自定义注解和动态加载

转载 作者:塔克拉玛干 更新时间:2023-11-02 21:18:40 25 4
gpt4 key购买 nike

我正在尝试为数据库同步开发 ORM,并决定试一试 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() 给出“class 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);

如果您仍然不知道我在说什么,感谢您阅读这篇冗长的文章 (-.

最佳答案

只获取您感兴趣的注释:

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

更新:

问题是 DexFile.getClass() 显然返回了一个代理。 OP 找到了答案并用解决方案更新了问题。

关于Java自定义注解和动态加载,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5105842/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com