Добро пожаловать в форум, Guest  >>   Войти | Регистрация | Поиск | Правила | В избранное | Подписаться
Все форумы / Java Новый топик    Ответить
 В контексте класса вызвать код времени загрузки  [new]
shalamyansky
Member

Откуда:
Сообщений: 197
Есть класс:

public class MyClass extends BaseClass{
    
    static public boolean test = false;

    static {
        registerClass( MyClass.class );
    }
    
}


Задача: вызвать метод registerClass( MyClass.class ) в момент загрузки, до вызова main().

Особое условие: код, вызывающий метод, должен находиться в контексте самого класса MyClass, никакой другой класс не может ничего "знать" про данный. То есть класс должен уметь зарегистрировать сам себя.

Казалось бы, для этой цели подошел бы статический блок инициации, как и показано в примере выше, но увы, код этого блока вызывается не в момент загрузки, а лишь в момент первого обращения к какому-либо полю или методу класса. То есть кто-то "снаружи" должен явно обратиться классу. Не подходит.

В Delphi, например, каждый модуль может содержать секцию initialization как раз для решения подобных задач.

Я в Java недавно, как тут это решается?

Поскольку работаю со Spring, попробовал добавить классу аннотацию @Component, что вроде бы должно было заставить систему создать на старте один экземпляр MyClass, и в результате статический блок должен был сработать. Не помогло.
17 ноя 20, 20:23    [22234148]     Ответить | Цитировать Сообщить модератору
 Re: В контексте класса вызвать код времени загрузки  [new]
забыл ник
Member

Откуда:
Сообщений: 3436
shalamyansky,

Бро, а какова твоя цель вообще? Ты явно пошел не по той дорожке. То о чем ты спрашиваешь может и возможно но это тобой же придуманный костыль. Какую проблему решаешь?
17 ноя 20, 22:08    [22234214]     Ответить | Цитировать Сообщить модератору
 Re: В контексте класса вызвать код времени загрузки  [new]
mayton
Member

Откуда: loopback
Сообщений: 49762
shalamyansky, какой такой метод main() ?

Дружище есть шаблоны такие как Singleton. Или Spring Bean в реализации Singleton.
Они - работают. Используй их.
17 ноя 20, 23:20    [22234250]     Ответить | Цитировать Сообщить модератору
 Re: В контексте класса вызвать код времени загрузки  [new]
shalamyansky
Member

Откуда:
Сообщений: 197
Цель - зарегистрировать класс :) Планируемая архитектура такая: есть базовый класс, который ничего не знает о своих наследниках. Но каждому наследнику дает возможность внести себя в поддерживаемый список методом registerClass.

public class BaseClass implements TargetInterface {

    @Override
    //TargetInterface implementation
    
    static private final List<Class> registeredClasses = new ArrayList<Class>(){};
    
    static protected boolean registerClass( Class cls ){ ... }

    static public Iterator<Class> getIterator(){ return registeredClasses.iterator(); }
    
}

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

Зачем это надо? Дело в том, что есть рабочий класс - потребитель интерфейса TargetInterface, который может принять реализующие его классы и с их помощью производить нужную работу:

import test.BaseClass;

public class Consumer{

    //cls must implemets TargetInterface
    public void applyClass( BaseClass cls  ){ ... }

    public void applyClasses(){
        Iterator<Class> iterator = BaseExtensionFunction.getIterator();
        while( iterator.hasNext() ){
            applyClass( iterator.next() );
        }
    }

    public void DoTargetWork(){}

}


В результате все, кто хотел, включили себя в работу класса Consumer, но явные зависимости на этапе компиляции нигде не прописаны. Это удобно, особенно когда наследуешь не свои классы. Просто создал наследника, в нем обеспечил вызов registerClass() - и все работает. Иначе приходится писать что-то такое ужасное:

import test.BaseClass;
import test.MyClass1;
import test.MyClass2;
import test.MyClass3;
//...

public class Consumer{

    //cls must implemets TargetInterface
    public void applyClass( BaseClass cls  ){ ... }

    public void applyClasses(){
        applyClass( MyClass1.class );
        applyClass( MyClass2.class );
        applyClass( MyClass3.class );
        //...
    }

    public void DoTargetWork(){}

}


Короче, классическая задача регистрации классов :) Удивлен, что она оказалось непростой в реализации. Даже пока еще и нереализованной.

Если совсем конкретно - пишу набор функций расширений для XSLT-процессора SAXON.
17 ноя 20, 23:40    [22234256]     Ответить | Цитировать Сообщить модератору
 Re: В контексте класса вызвать код времени загрузки  [new]
shalamyansky
Member

Откуда:
Сообщений: 197
mayton

Или Spring Bean в реализации Singleton.

Вот я и попробовал добавить @Component к MyClass, но что-то он не создался. Возможно, надо правильно установить @ComponentScan, но для этого надо еще понять, где же именно его установить. Вот, разбираюсь.
17 ноя 20, 23:47    [22234260]     Ответить | Цитировать Сообщить модератору
 Re: В контексте класса вызвать код времени загрузки  [new]
shalamyansky
Member

Откуда:
Сообщений: 197
Сорри, в сообщении от 23:40 вместо BaseExtensionFunction читать BaseClass.
17 ноя 20, 23:56    [22234262]     Ответить | Цитировать Сообщить модератору
 Re: В контексте класса вызвать код времени загрузки  [new]
mad_nazgul
Member

Откуда:
Сообщений: 5596
shalamyansky,

Вопрос:
Почему не используете готовые фреймворки, по типу Spring?
Создание своего инфраструктурного кода сегодня очень дорогое удовольствие.

А так... Пишите свой класслоадер, а там можете инициализировать всё что хотите и как хотите. :-)
18 ноя 20, 06:17    [22234327]     Ответить | Цитировать Сообщить модератору
 Re: В контексте класса вызвать код времени загрузки  [new]
Basil A. Sidorov
Member

Откуда:
Сообщений: 10760
shalamyansky
Цель - зарегистрировать класс :) Планируемая архитектура такая: есть базовый класс, который ничего не знает о своих наследниках. Но каждому наследнику дает возможность внести себя в поддерживаемый список методом registerClass.
Хреново вы Дельфи знаете :) У dll есть точка входа для событий подключения-отключения процессов и потоков в процессах. Именно это и позволяет "делать всякое".

JVM устроена по другому и не надо лезть с собственным уставом в чужой монастырь.
Если загрузка начинается с класса-потомка, то сначала конструируется класс-предок. Следовательно, ваш registerClass() должен быть в конструкторе.
Но есть засада: загрузка - действие разовое. Поэтому - не выёживайтесь: дёргайте в конструкторе класса-потомка защищённый финальный (может и статический) метод класса-предка.

P.S.
Вообще, конечно, логика - пипец.
Никто ничего не знает, но есть классы-потомки. Вы что - в детский дом их сдаёте и наследства лишаете???

Сообщение было отредактировано: 18 ноя 20, 07:02
18 ноя 20, 07:05    [22234332]     Ответить | Цитировать Сообщить модератору
 Re: В контексте класса вызвать код времени загрузки  [new]
chpasha
Member

Откуда:
Сообщений: 10035
если я правильно перевел смысл идеи, ТС - хочет получить в рантайме список ВСЕХ классов, реализующих определенный интерфейс (там еще есть "который желает", но это имхо глупость - тот кто "не желает", просто не должен реализовывать интерфейс). Если у нас спринг, то такое должно работать

public interface MyInterface {
}

@Component
public class MyInteface1Impl implements MyInterface{
}

@Component
public class MyInteface2Impl implements MyInterface{
}

class MyComponent {

  private final List<MyInterface> workers;

  @Autowired
  public MyComponent(List<MyInterface> workers) {
    this.workers = workers;
  }
}
18 ноя 20, 15:30    [22234669]     Ответить | Цитировать Сообщить модератору
 Re: В контексте класса вызвать код времени загрузки  [new]
maxkar
Member

Откуда:
Сообщений: 166
shalamyansky

Короче, классическая задача регистрации классов :) Удивлен, что она оказалось непростой в реализации. Даже пока еще и нереализованной.


Классической задаче - классическое решение! Задача "предоставить интерфейс, к которому позже подключаются разные реализации" решается с помощью ServiceLoader. Если хочется менее формальной прозы - учебник.

Если хочется красивого интерфейса - напишите обвязку вокруг этого стандартного механизма. Да, нужно все делать аккуратно (правильно манифест писать к библиотеке и т.п.). Но проблему-то решает.
18 ноя 20, 21:19    [22234934]     Ответить | Цитировать Сообщить модератору
Все форумы / Java Ответить