Найти все классы в пакете (и вызвать статические методы) во время выполнения - PullRequest
1 голос
/ 26 октября 2019

У меня есть пакет, в котором есть много классов, и у всех этих классов есть статический метод с именем onLoad. Я хочу вызвать метод onLoad при запуске программы, однако я не хочу жестко привязывать всех без исключения, например, classA.onLoad(); classB.onLoad(); и т. Д.

Как я могу перечислить все классы в пакете com.foo.bar.asd и запустить onLoad() на всех из них?

Заранее спасибо

Ответы [ 2 ]

0 голосов
/ 26 октября 2019

Вы можете использовать библиотеку reflections .

...
import org.reflections.Reflections;
import org.reflections.scanners.ResourcesScanner;
import org.reflections.scanners.SubTypesScanner;
import org.reflections.util.ClasspathHelper;
import org.reflections.util.ConfigurationBuilder;
import org.reflections.util.FilterBuilder;

public static void main(String[] args)
   throws NoSuchMethodException, IllegalAccessException, IllegalArgumentException, InvocationTargetException 
{
  Reflections reflections = new Reflections(new ConfigurationBuilder()
    .setScanners(new SubTypesScanner(false /* don't exclude Object.class */), new ResourcesScanner())
    .setUrls(ClasspathHelper.forClassLoader(ClasspathHelper.contextClassLoader()))
    .filterInputsBy(new FilterBuilder().include(FilterBuilder.prefix("com.foo.bar.asd"))));

  Set<Class<?>> classes = reflections.getSubTypesOf(Object.class);


  for (Class<?> clazz : classes)
  {
     Method method = clazz.getMethod("onLoad");
     method.invoke(null);
  }
}

Обратите внимание, что эта библиотека также имеет зависимости (guava.jar и javassist.jar).

0 голосов
/ 26 октября 2019

Я нашел этот вопрос довольно интересным, поэтому я нашел решение. Сложная часть здесь состоит в том, чтобы на самом деле найти все классы, которые находятся в данном пакете.

В этом примере я предполагаю, что все классы находятся в одном пакете, где класс C, и что все классы, кроме C иметь onLoad метод, который может быть недоступен (то есть private). Затем вы можете использовать следующий пример кода:

public final class C {

    public static void main(String[] args) throws Exception {
        for (Class<?> cls : getClasses(C.class)) {
            if (cls != C.class) {
                Method onLoad = cls.getDeclaredMethod("onLoad");
                onLoad.setAccessible(true);
                onLoad.invoke(null);
            }
        }
    }

    private static List<Class<?>> getClasses(Class<?> caller)
            throws IOException, URISyntaxException {
        return Files.walk(getPackagePath(caller))
                .filter(Files::isRegularFile)
                .filter(file -> file.toString().endsWith(".class"))
                .map(path -> mapPathToClass(path, caller.getPackage().getName()))
                .collect(Collectors.toList());
    }

    private static Class<?> mapPathToClass(Path clsPath, String packageName) {
        String className = clsPath.toFile().getName();
        className = className.substring(0, className.length() - 6);
        return loadClass(packageName + "." + className);
    }

    private static Path getPackagePath(Class<?> caller)
            throws IOException, URISyntaxException {
        String packageName = createPackageName(caller);
        Enumeration<URL> resources = caller.getClassLoader()
                .getResources(packageName);
        return Paths.get(resources.nextElement().toURI());
    }

    private static String createPackageName(Class<?> caller) {
        return caller.getPackage().getName().replace(".", "/");
    }

    private static Class<?> loadClass(String name) {
        try {
            return Class.forName(name);
        } catch (ClassNotFoundException e) {
            return null;
        }
    }
}

Я пропустил все проверки исключений, и такие операторы, как resources.nextElement(), могут даже выдавать исключение. Поэтому, если вы хотите охватить эти случаи, вам нужно добавить несколько проверок здесь и там.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...