title: Implementing Spring-like package scanning in Android
body: <p>I'm attempting to implement a package-scanning feature, similar to Spring's <code>component-scan</code>, for the Android framework I'm developing. Basically, I would like to be able to specify a base package, e.g. <code>com.foo.bar</code> and retrieve all <code>Class</code> instances that have a particular annotation. I don't want to have to register every component with my framework as that would defeat the purpose of the auto scanning.</p>
  
  <p>Based on my research, it seems that it's not possible with Java to retrieve resources given a package name using reflection. However, I briefly looked into the <a href="http://code.google.com/p/reflections/" rel="nofollow">Reflections framework</a>, and I'm wondering if there is an Android-compatible equivalent. If not, perhaps there is a slightly less obvious way to accomplish what I want to do.</p>
  
  <p>I looked into the Spring source a bit to see how they achieved this, but I don't think what they are doing would work within the Dalvik runtime.</p>
  
  <p><strong>Update</strong></p>
  
  <p>Currently, the below code has been the best I can do to retrieve all classes that contain a specific annotation, but frankly it's a pretty poor solution. It makes some really unsafe assumptions about the <code>ClassLoader</code> plus it scans (and loads) all application classes.</p>
  
  <pre><code>public Set&lt;Class&lt;?&gt;&gt; getClassesWithAnnotation(Class&lt;? extends Annotation&gt; annotation) {
      Set&lt;Class&lt;?&gt;&gt; classes = new HashSet&lt;Class&lt;?&gt;&gt;();
      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&lt;String&gt; entries = dex.entries();
          while (entries.hasMoreElements()) {
              String entry = entries.nextElement();
              Class&lt;?&gt; entryClass = dex.loadClass(entry, classLoader);
              if (entryClass != null &amp;&amp; entryClass.isAnnotationPresent(annotation)) {
                  classes.add(entryClass);
              }
          }
      }
      return classes;
  }
  </code></pre>