Implementación de paquetes parecidos a Spring en Android
Estoy intentando implementar una función de escaneo de paquetes, similar a la de component-scan
de Spring, para el framework de Android que estoy desarrollando. Básicamente, me gustaría ser capaz de especificar un paquete base, por ejemplo, com.foo.bar
y recuperar todas Class
instancias de Class
que tienen una anotación en particular. No quiero tener que registrar todos los componentes con mi framework, ya que esto podría anular el propósito de la exploración automática.
Basado en mi investigación, parece que no es posible con Java recuperar recursos dados un nombre de paquete usando la reflexión. Sin embargo, miré brevemente el marco de Reflections , y me pregunto si hay un equivalente compatible con Android. Si no, tal vez hay una manera un poco menos obvia de lograr lo que quiero hacer.
- Android Spring RestTemplate con proxy
- Cómo cambiar el tipo de contenido de MappingJacksonHttpMessageConverter de application / json; charset = UTF-8 a application / json
- Implementar OAuth2 con las credenciales de contraseña de propietario de recurso en Android
- Integra la aplicación con el sitio web social de primavera
- No se puede deserializar la instancia del objeto de START_ARRAY token en Spring Webservice
Miré un poco la fuente de Spring para ver cómo lograron esto, pero no creo que lo que estén haciendo funcionaría dentro del tiempo de ejecución de Dalvik.
Actualizar
Actualmente, el siguiente código ha sido el mejor que puedo hacer para recuperar todas las clases que contienen una anotación específica, pero francamente es una solución bastante pobre. Hace algunas suposiciones realmente inseguras sobre el ClassLoader
y escanea (y carga) todas las clases de aplicación.
public Set<Class<?>> getClassesWithAnnotation(Class<? extends Annotation> annotation) { Set<Class<?>> classes = new HashSet<Class<?>>(); Field dexField = PathClassLoader.class.getDeclaredField("mDexs"); dexField.setAccessible(true); PathClassLoader classLoader = (PathClassLoader) Thread.currentThread().getContextClassLoader(); DexFile[] dexs = (DexFile[]) dexField.get(classLoader); for (DexFile dex : dexs) { Enumeration<String> entries = dex.entries(); while (entries.hasMoreElements()) { String entry = entries.nextElement(); Class<?> entryClass = dex.loadClass(entry, classLoader); if (entryClass != null && entryClass.isAnnotationPresent(annotation)) { classes.add(entryClass); } } } return classes; }
- Xml spring para android con gradle
- Conecte con los clientes de iOS y Android a SockJS Backend
- Establecer encabezados utilizando resorte android resttemplate y anotaciones android
- El resorte de solicitud de varias partes no enlaza datos de archivo
- Subida múltiple de archivos con OkHttp + Spring
- No se puede configurar LocalContainerEntityManagerFactoryBean desde @EntityScan, asegúrese de que un bean apropiado esté registrado
- Seguridad de Primavera Angularjs + Android REST
- Añadiendo primavera para la dependencia de Android a gradle + proyecto de estudio Android
Comparto la opinión de Joop Eggen y considero que su enfoque es bueno. En Android intento evitar las características usuales de la aplicación web que conducen a un inicio de aplicación duradero. No utilizo la reflexión ni la exploración de paquetes.
Pero si quieres … si lo entiendo correctamente quieres tener una anotación para una clase. En lugar de utilizar las anotaciones, también puede utilizar las interfaces de marcadores (para tener más posibilidades).
1) Mira
- Anotación: Anotación personalizada de Java y carga dinámica
Tiene una implementación en la pregunta que sólo contesta a su pregunta. - Anotación: Analizar anotaciones de Java en tiempo de ejecución
- Interfaz: Buscar clases Java implementando una interfaz
- Interfaz: ¿Es algo similar a ServiceLoader en Java 1.5?
- Interfaz: ¿Cómo puedo obtener una lista de todas las implementaciones de una interfaz mediante programación en Java?
- Interfaz: Ya que el enfoque es costoso, tal vez el ServiceLoader sea un compromiso entre el tiempo de ejecución y el confort, ya que sólo carga las clases dadas en el archivo de servicios. Por otro lado si sólo las clases con una determinada interfaz están en su paquete, entonces el ServiceLoader no es tan rápido.
2) AndroidAnnotations
Preferiría la forma en que funciona AndroidAnnotations (tal vez una integración en AndroidAnnotations es la forma preferible): Añade automáticamente un paso de compilación extra que genera código fuente, utilizando la herramienta de procesamiento de anotaciones Java estándar. Por lo tanto, en lugar del análisis en tiempo de ejecución, ejecuta código basado en las anotaciones generadas durante el tiempo de compilación.
Creo que la anotación Bean / EBean podría funcionar para usted (solo clase individual): https://github.com/excilys/androidannotations/wiki/Enhance%20custom%20classes
Una función de escaneo no está disponible, vea este hilo
3) Escribir su propio procesador de anotación
- Consulte APT (Herramienta de procesamiento de anotaciones) . La idea sería generar una función estática que devuelva una lista de clases que están anotadas, de modo que no se necesita escanear clases.
- Un recurso muy bueno es http://javadude.com/articles/annotations/index.html
Quería encontrar toda la subclase en tiempo de ejecución. Así que he estado buscando la exploración de clase de android. Este es mi código final de lo que reuní en la web. Usted recibirá la idea.
public static void findSubClasses(Context context, Class parent) { ApplicationInfo ai = context.getApplicationInfo(); String classPath = ai.sourceDir; DexFile dex = null; try { dex = new DexFile(classPath); Enumeration<String> apkClassNames = dex.entries(); while (apkClassNames.hasMoreElements()) { String className = apkClassNames.nextElement(); try { Class c = context.getClassLoader().loadClass(className); if (parent.isAssignableFrom(c)) { android.util.Log.i("nora", className); } } catch (ClassNotFoundException e) { // TODO Auto-generated catch block e.printStackTrace(); } // android.util.Log.i("nora", className); } } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } finally { try { dex.close(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } }
Echa un vistazo a ClassPathScanner de Vogar. Se utiliza para encontrar casos de prueba en la ruta de clase.
EDITAR:
Encontré este problema en el rastreador de problemas de Android. Parece que ClassLoader.getResource(String)
está 'trabajando como se esperaba', en que devuelve null
. Esto es esperado porque el DalvikVM no mantiene los recursos alrededor después de compilar. Hay soluciones descritas en el problema, pero puede haber otra forma de acceder a las clases que desee.
Utilice PackageManager
para obtener una retención de una instancia de ApplicationInfo
. ApplicationInfo
tiene un campo público llamado sourceDir
que es la ruta completa (una String
) a la ubicación del directorio de origen para esa aplicación. Crear un File
de esta String
, y usted debe ser capaz de navegar a su paquete en el directorio de origen. Una vez allí, puede utilizar el método de mi respuesta original para encontrar las clases que está buscando.
String applicationSourceDir = getPackageManager().getApplicationInfo(androidPackageName, 0).sourceDir;
/EDITAR
Debe ser capaz de utilizar ClassLoader.getResource(String)
para obtener una URL
para su paquete específico (el pasado en String
es el nombre del paquete que está interesado en delimitado por separadores de ruta en lugar de puntos). Con esta URL
puede llamar a getFile()
, desde el cual puede crear un File
Java en la carpeta del paquete. Llame a packageFile.listFiles()
desde allí, y tiene sus clases / subpaquetes.
Sea recursivo con los subpaquetes y con las clases encuentre el objeto Class
utilizando el método Class.forName(String)
estático.
En su proceso de creación de java incorporar la ruta de acceso de clase de exploración, la generación de inyección de datos / código. Esto también podría ser portado a Dalvik. Es aún más eficiente que el escaneado dinámico.
- Drawable to Bitmap, Drawable desconocido tamaño / dimensión
- Intención MMS de Android con texto de imagen y cuerpo