Scheme 1: The reflections frame (this frame dependent com.google.guava)
1, reflections framework Address: https://github.com/ronmamo/reflections
2, Project Dependencies
<dependency> <groupId>org.reflections</groupId> <artifactId>reflections</artifactId> <version>0.9.11</version> </dependency> <dependency> <groupId>com.google.guava</groupId> <artifactId>guava</artifactId> <version>21.0</version> </dependency>
3, implementation code
// reference into the package name to be scanned Reflections f = new Reflections("com.ggband.netty.execute.command"); // into the reference target class notes Set<Class<?>> set = f.getTypesAnnotatedWith(Cmd.class);
Option II: The scanning ClassLoader
1, implementation code
package com.ggband.netty; import java.io.File; import java.io.IOException; import java.lang.annotation.Annotation; import java.net.JarURLConnection; import java.net.URL; import java.net.URLDecoder; import java.util.Enumeration; import java.util.HashSet; import java.util.Set; import java.util.jar.JarEntry; import java.util.jar.JarFile; public class Scanner { /** * Get all the packages from the package in Class * * @param packageName * @return */ public Set<Class<?>> getClasses(String packageName) throws Exception { // set of first class category // List <Class <>> classes = new new ArrayList <Class <>> ();?? The Set <Class <= >> classes? New new HashSet <> (); // if loop iterations Boolean recursive this = to true ; // Get the name of the package and the replacement String packageDirName packageName.replace = (, '/' '.' ); // definition of an enumerated set of things and loop to handle this directory the Enumeration <the URL> dirs; the try { dirs = Thread.currentThread () getContextClassLoader () getResources (packageDirName);.. // iteration of the loop continues the while (dirs.hasMoreElements ()) { // get the next element of the URL URL = dirs.nextElement (); // get agreement name String Protocol = url.getProtocol (); // if the form of files stored on the server IF ( "file" .equals (Protocol)) { // get the package physical path String filePath = URLDecoder.decode (url .getFile (), "UTF-. 8" ); //Scan files as files in the entire package, and added to the collection addClass (classes, filePath, packageName) ; } The else IF ( "jar" .equals (Protocol)) { // if jar package file // define a JarFile to JarFile to jar; the try { // Get jar jar = . ((JarURLConnection to) url.openConnection ()) getJarFile ( ); // from this package to obtain an enumeration class jar the enumeration <the JarEntry for> = entries It jar.entries (); // same loop iterations performed the while (entries.hasMoreElements ()) { //An entity acquired in the jar can be a directory and some other jar file META-INF bag as other documents the JarEntry for the entry = entries.nextElement (); Name String = entry.getName (); // if by starting with / IF (name.charAt (0) == '/' ) { // Get string behind name name.substring = (. 1 ); } // if the package name and the same as defined in the first part IF (name.startsWith (packageDirName)) { int IDX = name.lastIndexOf ( '/' ); // if the ending "/" is a packet IF ! (IDX = - 1 ) { // Get the package name "/" replace "." the packageName name.substring = (0, IDX) .replace ( '/', '.' ); } // If you can go on and iteration is a package IF ((IDX! = -1) || recursive This) { // If it is not a .class file and directory IF (name.endsWith (. "Class") &&! Entry. the isDirectory ()) { // remove behind ".class" Get real class name String className = name.substring (packageName.length () +. 1, name.length () -. 6 ); the try { // Add to classes classes.add (the Class.forName (the packageName + + '.' className)); } catch (ClassNotFoundException e) { e.printStackTrace (); } } } } } } catch (IOException e) { e.printStackTrace (); } } } } catch (IOException e) { e.printStackTrace (); } return classes; } public void addClass(Set<Class<?>> classes, String filePath, String packageName) throws Exception { File[] files = new File(filePath).listFiles(file -> (file.isFile() && file.getName().endsWith(".class")) || file.isDirectory()); assert files != null; for (File file : files) { String fileName = file.getName(); if (file.isFile()) { String classsName = fileName.substring(0, fileName.lastIndexOf(".")); if (!packageName.isEmpty()) { classsName = packageName + "." + classsName; } doAddClass(classes, classsName); } } } public void doAddClass(Set<Class<?>> classes, final String classsName) throws Exception { ClassLoader classLoader = new ClassLoader() { @Override public Class<?> loadClass(String name) throws ClassNotFoundException { return super.loadClass(name); } }; classes.add(classLoader.loadClass(classsName)); } public <A extends Annotation> Set<Class<?>> getAnnotationClasses(String packageName, Class<A> annotationClass) throws Exception { // find annotated classes with the annotationClass the Set <Class <= >> the Controllers? New new HashSet <> (); Set<Class<?>> clsList = getClasses(packageName); if (clsList != null && clsList.size() > 0) { for (Class<?> cls : clsList) { if (cls.getAnnotation(annotationClass) != null) { controllers.add(cls); } } } return controllers; } }
2, use:
Set<Class<?>> set = new Scanner().getAnnotationClasses("com.ggband.netty.execute.command", Cmd.class);
Expansion: You can now implement your own business, and such scan com.ggband.netty.execute.command coated Cmd annotated classes to get an instance Cmd notes and annotated value classes
Map<String, Command> beanContainer = new HashMap<>();
try {
//@1 采用reflections 框架(此框架依赖com.google.guava)
// Reflections f = new Reflections("com.ggband.netty.execute.command");
// Set<Class<?>> set = f.getTypesAnnotatedWith(Cmd.class);
//@2 采用ClassLoader扫描
Set<Class<?>> set = new Scanner().getAnnotationClasses("com.ggband.netty.execute.command", Cmd.class);
for (Class<?> c : set) {
Object bean = c.newInstance();
Cmd annotation = c.getAnnotation(Cmd.class);
beanContainer.put(Arrays.toString(annotation.value()), (Command) bean);
}
} catch (Exception e) {
e.printStackTrace();
}