Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Java: Общие вопросы > поиск классов определенного интерфейса в пакете


Автор: ALKS 21.4.2006, 11:52
Задача примерно такая: 
Известно имя пакета (ну скажем net.mycoolproject.sypertool.*) 
Известно что в этом пакете могут быть классы имплементирующее определённый интерфейс (и более того скажеи все такие классы, используя Java 5, аннотированы определенным образом)
Где пакет находиться неизвестно. (ну понятно что он где-то возможно внутри какого-то jar в classpath или jre/lib/ext или далее по списку возможных мест)
Известно что искомые классы могут быть еще не загружены. т.е. искать в списке загруженных лоадером классов не получиться...
Нужно все такие классы найти.

Понятно что можно проверить все jar-ы (и не только) во всех местах, выщемить таки нужное место где наш пакет, пробежаться по всем классам внутри него... трудно и не-изящно... smile

Есть ли другие пути? можно ли скажем вынудить загрузчик загрузить все классы в пакете(тогда хоть искать физическое расположение пакета не придеться)? можно ли получить список всех классов в пакете проаннатированных определенным образом? хоть что не будь? 

Автор: powerOn 21.4.2006, 12:44
С пакетами можно работать через java.lang.Package. Может он чем поможет... 

Автор: ALKS 21.4.2006, 13:09
Изучал я его... правда глубоко тестовый код не писал(ночью юуду щас времени нету...) он может вернуть информацию о пакете по имени включая аннотации самого пакета(если я верно понял) и последнее интересно, ведь в эту анотацию пакета можно в общем-то вписать интересующие нас классы из пакета. на то и мета-данные. правда не очень понятно как можно аннотировать сам пакет... может кто-то подбросит пример? 

Автор: COVD 21.4.2006, 15:02
Понятно, что вам прежде всего надо решить вашу задачу. Но все-таки любопытно, а для чего это? В какого класса приложениях или ситуациях такая необходимость возникает? 

Автор: ALKS 21.4.2006, 15:53
Грубо говоря - плагины. куча мелких и не очень классов реализующих определенный интерфейс и раскиданных по разным пакетам и даже jar. есть несколько инсталиций определенного приложения которое грузит их в момент запуска(однократная операци (по этому нестрашно если оно будет запускаться даже пару минут) и потом использует. Само приложение знает только об интефейсе естественно. Конечно ничего не мешает просто перечислить все используемы классы в конфигурациооных файлах, например. Но лень - 40 строк можно заменить тремя... с именами пакетов smile 

Автор: Stampede 21.4.2006, 20:38
Может вот это придаст мыслям некоторое направление?

Я тоже как-то думал о плагинной архитектуре для одной проги. Понятно, что там пахло своим загрузчиком, менеджером плагинов, рефлексией и пр. Убивало то, что стартап правращался в весьма длительную процедуру: как ни крути, а надо прошерстить весь classpath и не только.

И вот думал я, значить, думал, и вдруг пришло решение: а надо чекать не все места, а только изменения! То есть идея такая. В самый первый раз проверяется все что можно - и по результатам этой проверки генерится XML-описатель всех найденных плагинов. После этого при каждом последующем запуске сравнивается текущий classpath с ранее сохраненным, и процедура повторяется только для новых путей. Для всех остальных проверка осуществляется только на наличие изменений. Результаты снова записываются в описатель.

Таким же макаром можно было бы реализовать механизм горячего развертывания плагинов: слушать изменения в директориях и запускать процедуру поиска.

Прогу я тогда так и не собрался сделать, а вот недавно наткнулся на одну библиотечку, которая, возможно, оказалась бы хорошим подспорьем в реализации этого механизма. Назвается Java Plugin Framework, находится вот здесь: http://jpf.sourceforge.net/.

Посмотри. может как-то сгодится.
 

Автор: ALKS 21.4.2006, 21:40
Stampede, спасибо. идея не дурственна, но смысл в том что мы лентяи и вообще не хотим замарачиваться с поиском smile

Чем закончились исследования с классом Package, если кому-то интересно:

1. создаем ананотацию нужного нам вида. ну например:
Код

package net.mycoolproject.sypertool;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.PACKAGE)
public @interface CoolTest {

    String comment(); 
}


2. создаем фаил package-info.java (помещаем его внутри нашего пакета, естественно) следующего содержания
Код

@CoolTest(comment="Super test") 
package net.alexei.validator.configcheck;

Если кто-то не догадался, то этот спицифический класс со строго таким именем используеться для анатоций пакета (и кроме того еще для javadoc но это уже другая тема)

3. теперь, там где вам хочется вы можете вызвать такой вот код:
Код

Package pack = Package.getPackage("net.mycoolproject.sypertool");
        
if (pack != null ) {
    CoolTest сoolTest = pack.getAnnotation(CoolTest.class);
    if (сoolTest != null) {
        System.out.println(сoolTest.comment());
    }
}

Что оно вам вернет вы наверняка догадались smile

Остальное дело техники. никто не мешает вам в этой анотации к пакету перечислить(например массивом) интересующие вас объекты класса Class smile. Т.е. сам пакет заботиться о том чтобы проинформировать вас например о том какие классы в нем есть. Этот путь конечно далек от моей мечты, потому что требует немножко специальной работы над пакетом с "плагинами", но хоть что-то.
 

Автор: LSD 22.4.2006, 00:51
Вот это я понимаю smile

Добавил в FAQ. 

Автор: ALKS 22.4.2006, 09:43
LSD, там ошибка в package-info.java неправильное имя пакета - должно быть net.mycoolproject.sypertool. Раз уж ты в FAQ это запихнул, то надо исправить smile 

Автор: LSD 22.4.2006, 10:44
Fixed 

Автор: ALKS 22.4.2006, 11:36
Возвращаясь собственно к теме топа, вот что получилось окончательно (мне понравился результат по-этому очень хочется поделиться smile )

аннотация (net.mycoolproject.IMonsterPlugin это интерфейс, для чистоты эксперемента он вынесен в другой пакет ):
Код

package net.mycoolproject.sypertool;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;


@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.PACKAGE)
public @interface @CoolTest{
    Class<? extends net.mycoolproject.IMonsterPlugin>[] monsters();
}


package-info.java (Hydra,Cerberus,Cyclop - это классы из нашего пакета, имплементирующие net.mycoolproject.IMonsterPlugin ):
Код

@CoolTest(monsters={Hydra.class,Cerberus.class,Cyclop.class}) 
package net.mycoolproject.sypertool;


использование (предпологаеться что Hydra,Cerberus,Cyclop имеют конструктор без параметров, а net.mycoolproject.IMonsterPlugin имеет единственный метод: beCool() ):
Код


Package pack = Package.getPackage("net.mycoolproject.sypertool");    
if (pack != null ) {
    CoolTest a = pack.getAnnotation(CoolTest.class);
    if (a != null) {
        for (Class<? extends net.mycoolproject.IMonsterPlugin> c : a.checkClasses() ) {
            //создаем и используем объект найденного класса.
            net.mycoolproject.IMonsterPlugin monster = c.getConstructor(null).newInstance();
            check.beCool();
        }
    }
}


Вот. А теперь внимательно посмотрим на то, что получилось:
Уже на стадии компиляции проверяеться, что во-первых все перечисленные в аннотации классы существуют в нашем пакете и, что во-вторых они действительно имплементируют нужный нам интерфейс! это гораздо больше чем, например, имя класса указаное в конфиге, это дало много информации вызывающей программе и подстраховало нас от ряда ошибок времени выполнения.

А Class.forName() в вызывающей програме-то нету, ну разве не мило? smile

P.S. вообще ИМХО аннотации - самое мощное новшество в Java 5. в связке с рефлексией можно чудеса творить (и JUnit 4 тому живой пример)
P.P.S. возвращаясь к теме топа - всё, это максимум что можно вытянуть из анотаций для поставленной задачи. единственное с чем можно по-извращаться - автоматическая генерация package-info.java. Ну... я конечно лентяй, но уж не настолько smile
P.P.P.S. возвращаясь к теме топа - всё еще интересуют альтернативные пути решения проблеммы.... ??? 

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)