Пользовательская аннотация Java и динамическая загрузка - PullRequest
6 голосов
/ 24 февраля 2011

Я пытаюсь разработать 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 () дает «класс 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);

Если вы все еще не понимаете, о чем я говорю, спасибо за чтение этого длинного поста (-.

1 Ответ

2 голосов
/ 24 февраля 2011

Получите только интересующую вас аннотацию:

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

Обновление:

Проблема в том, что DexFile.getClass (), очевидно, возвращает прокси.ОП нашел ответ и обновил вопрос решением.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...