Подтвердить что ты не робот

В spring bean возможно ли иметь метод выключения, который может использовать транзакции?

В методе уничтожения spring bean я хочу выполнить некоторые запросы для очистки некоторых вещей в базе данных. spring, похоже, не позволяет это каким-либо образом найти.

Ошибка всегда есть что-то вроде:

Вызов метода уничтожения bean с именем "someBean": org.springframework.beans.factory.BeanCreationNotAllowedException: Ошибка при создании bean с именем 'transactionManager': Singleton beanсоздание не допускается, пока синглтоны этого factory находятся в уничтожение (не запрашивать beanиз BeanFactory в методе уничтожения реализация!)

Следующее сообщит spring, чтобы вызвать shutdownDestroy после того, как bean больше не нужен. Но при попытке использовать транзакции я получаю вышеуказанную ошибку.

<bean id="someId" name="someName" class="someClass"
 destroy-method="shutdownDestroy"/>

То же самое верно, когда я включаю общие аннотации жизненного цикла, используя:

<bean class="org.springframework. ... .CommonAnnotationBeanPostProcessor"/>

а затем отметьте метод @PreDestroy. Этот метод также не может использовать транзакции.

Есть ли способ сделать это?

EDIT: Благодарю! У меня был bean реализовать SmartLifecycle и добавить следующее, и он работает очень хорошо.

private boolean isRunning = false;

@Override
public boolean isAutoStartup() {return true;}

@Override
public boolean isRunning() {return isRunning;}

/** Run as early as possible so the shutdown method can still use transactions. */
@Override
public int getPhase() {return Integer.MIN_VALUE;}

@Override
public void start() {isRunning = true;}

@Override
public void stop(Runnable callback) {
    shutdownDestroy();
    isRunning = false;
    callback.run();
}

@Override
public void stop() {
    shutdownDestroy();
    isRunning = false;
}
4b9b3361

Ответ 1

Интересный вопрос. Я бы сказал, что вы сможете это сделать чтобы ваш bean реализовал SmartLifeCycle.

Таким образом, если ваш метод int getPhase(); возвращает Integer.MAX_VALUE, он будет одним из первых, который будет вызываться, когда ApplicationContext окончательно выключится.

Справка:

Ответ 2

Я сталкиваюсь с этой же проблемой. После проверки исходного кода spring U может попытаться реализовать

public class SomeBean implements ApplicationListener<ContextClosedEvent> {
    public void onApplicationEvent(ContextClosedEvent event) {
        stopHook();
    }
}

onApplicationEvent будет вызван до bean destory, вы можете проверить его на spring org.springframework.context.support.AbstractApplicationContext # doClose. Я вставляю его ниже, поэтому ContextEvent → LifeCycle → bean destory.

        try {
            // Publish shutdown event.
            publishEvent(new ContextClosedEvent(this));
        }
        catch (Throwable ex) {
            logger.warn("Exception thrown from ApplicationListener handling ContextClosedEvent", ex);
        }

        // Stop all Lifecycle beans, to avoid delays during individual destruction.
        try {
            getLifecycleProcessor().onClose();
        }
        catch (Throwable ex) {
            logger.warn("Exception thrown from LifecycleProcessor on context close", ex);
        }

        // Destroy all cached singletons in the context BeanFactory.
        destroyBeans();

        // Close the state of this context itself.
        closeBeanFactory();

        // Let subclasses do some final clean-up if they wish...
        onClose();