现在我的工程里有一个接口,另外有几个实现了这个接口的类,在另外一个应用的类中如何得到实现接口的这些类的类名。当然这些类是不确定的,因为还可以增加这样的类来扩展,要求在增加这样的类时不改动应用类的代码。
比如:现在我有一个接口Tool,
实现这个接口的类:Plane,Bus
应用的类:Application
要是通过映射,该怎么实现?

解决方案 »

  1.   

    可以考虑类似SPI(Service Provider Interface)的机制
      

  2.   

    基本思想:
    1,获得接口。
    2,根据是否在同一个包下,遍历文件信息。
    3,得到实现该接口的所有类。代码实现:package com.snow.manager.test;import java.io.File;
    import java.io.IOException;
    import java.net.URL;
    import java.util.ArrayList;
    import java.util.Collections;
    import java.util.Enumeration;
    import java.util.Iterator;
    import java.util.List;public class GetClassName{
    Class<?> clz = this.getClass();
    public static void main(String[] args) {
    GetClassName gcn = new GetClassName();
    try {
    List<Class<?>> l = gcn.getAllClassesByInterface(Tool.class, true);
    for (Iterator<Class<?>> iterator = l.iterator(); iterator.hasNext();) {
    Object object = (Object) iterator.next();
    System.out.println(object);
    }
    } catch (ClassNotFoundException e) {
    e.printStackTrace();
    } catch (IllegalStateException e) {
    e.printStackTrace();
    } catch (IOException e) {
    e.printStackTrace();
    }
    }

    /** 
         * 获取接口的所有实现类 
         * @param interfaceClass 接口类 
         * @param samePackage    是否为同一包路径下 
         * @return 
         * @throws ClassNotFoundException  
         * @throws IOException  
         */  
        public static List<Class<?>> getAllClassesByInterface(Class<?> interfaceClass, boolean samePackage)   
            throws IOException, ClassNotFoundException, IllegalStateException {  
              
            if (!interfaceClass.isInterface()) {  
                throw new IllegalStateException("Class not a interface.");  
            }  
              
            ClassLoader $loader = interfaceClass.getClassLoader();  
    //      ClassLoader $loader = Thread.currentThread().getContextClassLoader();  
            /** 获取包名称 */  
            String packageName = samePackage ? interfaceClass.getPackage().getName() : "/";  
            return findClasses(interfaceClass, $loader, packageName);  
        }  
          
        /** 
         * 获取实现接口的实现类文件 
         * @param interfaceClass 
         * @param loader 
         * @param packageName 
         * @return 
         * @throws IOException 
         * @throws ClassNotFoundException 
         */  
        private static List<Class<?>> findClasses(Class<?> interfaceClass, ClassLoader loader, String packageName)   
            throws IOException, ClassNotFoundException {  
              
            List<Class<?>> allClasses = new ArrayList<Class<?>>();  
            /** 获取包路径 */  
            String packagePath = packageName.replace(".", "/");  
            if (!packagePath.equals("/")) {  
                Enumeration<URL> resources = loader.getResources(packagePath);  
                while (resources.hasMoreElements()) {  
                    URL $url = resources.nextElement();  
                    allClasses.addAll(findResources(interfaceClass, new File($url.getFile()), packageName));      
                }     
            } else {  
                String path = loader.getResource("").getPath();  
                allClasses.addAll(findResources(interfaceClass, new File(path), packageName));  
            }  
            return allClasses;  
        }  
          
        /** 
         * 获取文件资源信息 
         * @param interfaceClass 
         * @param directory 
         * @param packageName 
         * @return 
         * @throws ClassNotFoundException 
         */  
        @SuppressWarnings("unchecked")  
        private static List<Class<?>> findResources(Class<?> interfaceClass, File directory, String packageName)   
            throws ClassNotFoundException {  
              
            List<Class<?>> $results = new ArrayList<Class<?>>();  
            if (!directory.exists()) return Collections.EMPTY_LIST;  
            File[] files = directory.listFiles();  
            for (File file : files) {  
                if (file.isDirectory()) {  
                    // 文件夹-->继续遍历  
                    if (!file.getName().contains(".")) {  
                        if (!packageName.equals("/")) {  
                            $results.addAll(findResources(interfaceClass, file, packageName + "." + file.getName()));  
                        } else {  
                            $results.addAll(findResources(interfaceClass, file, file.getName()));  
                        }                         
                    }                 
                } else if (file.getName().endsWith(".class")){  
                    Class clazz = null;  
                    if (!packageName.equals("/")) {  
                        clazz = Class.forName(packageName + "." + file.getName().substring(0, file.getName().length() - 6));  
                    } else {  
                        clazz = Class.forName(file.getName().substring(0, file.getName().length() - 6));  
                    }   
                    //比较接口和该文件是否相同。
                    if (interfaceClass.isAssignableFrom(clazz) && !interfaceClass.equals(clazz)) {  
                        $results.add(clazz);  
                    }                 
                }  
            }  
            return $results;  
        }  
    }interface Tool {

    }class Plane implements Tool {

    }class Bus implements Tool {

    }class Bicycle implements Tool {

    }