Spring IoC контейнер: Java конфигурация, использование аннотации @Bean, получение обратных вызовов жизненного цикла

Любые классы, определенные с помощью аннотации @Bean, поддерживают обычные обратные вызовы жизненного цикла и могут использовать аннотации @PostConstruct и @PreDestroy из JSR-250.

Обычные обратные вызовы жизненного цикла Spring также полностью поддерживаются. Если bean-компонент реализует InitializingBean, DisposableBean или Lifecycle, контейнер вызывает их соответствующие методы.

Стандартный набор *Aware интерфейсов (таких как BeanFactoryAware, BeanNameAware, MessageSourceAware, ApplicationContextAware и т. д.) также полностью поддерживается.

Аннотация @Bean поддерживает указание произвольных методов обратного вызова инициализации и уничтожения, во многом как атрибуты init-метода и destroy-метода Spring XML для элемента bean, как показано в следующем примере:

Java

public class BeanOne {

    public void init() {
        // логика инициализации
    }
}

public class BeanTwo {

    public void cleanup() {
        // логика разрушения
    }
}

@Configuration
public class AppConfig {

    @Bean(initMethod = "init")
    public BeanOne beanOne() {
        return new BeanOne();
    }

    @Bean(destroyMethod = "cleanup")
    public BeanTwo beanTwo() {
        return new BeanTwo();
    }
}

Kotlin

class BeanOne {

    fun init() {
        // логика инициализации
    }
}

class BeanTwo {

    fun cleanup() {
        // логика разрушения
    }
}

@Configuration
class AppConfig {

    @Bean(initMethod = "init")
    fun beanOne() = BeanOne()

    @Bean(destroyMethod = "cleanup")
    fun beanTwo() = BeanTwo()
}

По умолчанию бины, определенные в конфигурации Java, которые имеют public close или shutdown метод, автоматически зачисляются с обратным вызовом уничтожения. Если у вас есть public close или shutdown метод, и вы не хотите, чтобы он вызывался при закрытии контейнера, вы можете добавить @Bean(destroyMethod="") в определение вашего бина, чтобы отключить режим по умолчанию.

Возможно, вы захотите сделать это по умолчанию для ресурса, который вы получаете с помощью JNDI, поскольку его жизненный цикл управляется вне приложения. В частности, всегда делайте это для DataSource, так как известно, что это проблематично на серверах приложений Java EE.

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

Java

@Bean(destroyMethod="")
public DataSource dataSource() throws NamingException {
    return (DataSource) jndiTemplate.lookup("MyDS");
}

Kotlin

@Bean(destroyMethod = "")
fun dataSource(): DataSource {
    return jndiTemplate.lookup("MyDS") as DataSource
}

Кроме того, с помощью методов @Bean вы обычно используете программные поиски JNDI, используя либо Spring JndiTemplate или JndiLocatorDelegate, либо прямое использование JNDI InitialContext, но не JndiObjectFactoryBean вариант (который заставит вас объявить возвращаемый тип как тип FactoryBean вместо фактического целевого типа, что усложняет его использование для вызовов перекрестных ссылок в других методах @Bean, которые намереваются ссылаться на предоставленный ресурс здесь).

В случае BeanOne из примера выше предыдущего примечания было бы одинаково правильно вызывать метод init() непосредственно во время построения, как показано в следующем примере:

Java

@Configuration
public class AppConfig {

    @Bean
    public BeanOne beanOne() {
        BeanOne beanOne = new BeanOne();
        beanOne.init();
        return beanOne;
    }

    // ...
}

Kotlin

@Configuration
class AppConfig {

    @Bean
    fun beanOne() = BeanOne().apply {
        init()
    }

    // ...
}

Когда вы работаете непосредственно в Java, вы можете делать со своими объектами все, что угодно, и вам не всегда нужно полагаться на жизненный цикл контейнера.


Читайте также:


Комментарии

Популярные сообщения из этого блога

Методы класса Object в Java

Как получить текущий timestamp в Java

Основные опции JVM для повышения производительности и отладки