2011-02-24 15 views
6

Próbuję opracować ORM do synchronizacji bazy danych i postanowiłem dać refleksji Java. Mam biblioteki, który definiuje Synchronized adnotacji jak tenAdnotacja Java i dynamiczne ładowanie

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

w Android projektu Używam tego adnotacji oznaczyć klasę modelu

@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; 
} 

Po jakimś dochodzeniu „ładowarka” metoda została ostatecznie napisane, że pozwala na odkrywanie Klasy modelowe w bieżącym apk. Powinien pobrać wszystkie klasy oznaczone jako "zsynchronizowane", ale problem polega na tym, że getAttribute (Synchronised.class) nie działa. Ręczne iterowanie adnotacji i wyszukiwanie atrybutu (instanceof, itp.) Również nie działa. Podczas debugowania zauważyłem, że adnotacja pochodząca z odbicia jest w rzeczywistości proxy (getClass() daje "klasę Proxy2", podczas gdy adnotacja.AnnotationType() zwraca poprawną nazwę) - to tłumaczy, dlaczego nie udało mi się osiągnąć poprzednich prób. Podczas próby rzutowania bezpośrednio - wyrzucany jest wyjątek (zrozumiałe). Zasadniczo brakuje mi tutaj, więc każdy pomysł jest mile widziany.

metoda model załadunku (w projekcie biblioteki):

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;  
    } 

[ROZWIĄZANIE] Ładowarka klasa musi być przykuty tak:

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

Jeśli nadal nie masz pojęcia, co mam . mówisz, dzięki za przeczytanie tego długiego posta (-

Odpowiedz

2

uzyskać tylko adnotację, że jesteś zainteresowany:

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

Aktualizacja:

Problemem jest to, że DexFile.getClass() najwyraźniej powraca proxy. OP znalazł anser i zaktualizował pytanie za pomocą rozwiązania.

Powiązane problemy