Метод инициализации в Spring Controller (версия аннотации)

105

Я конвертирую контроллер в более новую версию аннотации. В старой версии я использовал для указания метода инициализации в springmvc-servlet.xml, используя:

<beans>
    <bean id="myBean" class="..." init-method="init"/>
</beans>

Как я могу указать метод инициализации, используя версию аннотации?

Krt_Malta
источник
См. Также stackoverflow.com/questions/1088550
skaffman

Ответы:

238

Ты можешь использовать

@PostConstruct
public void init() {
   // ...
}
Йохан Сьёберг
источник
1
Вы правы, его «Общие аннотации 1.0», Java1.7 тоже подойдут.
Grim
Если вам нужно использовать User из SecurityContextHolder, в момент PostConstruct он не инициализируется. Его нужно использовать как метод без сохранения состояния. (getUser () ... {return Security ... user ();}
Жоао Поло
общественное или частное
anshulkatta
20

В качестве альтернативы вы можете заставить свой класс реализовать InitializingBeanинтерфейс для предоставления функции обратного вызова ( afterPropertiesSet()), которую ApplicationContext будет вызывать при создании bean-компонента.

Мэтт Би
источник
4

Есть несколько способов перехватить процесс инициализации в Spring. Если вам нужно инициализировать все beans и автоматически подключать / вводить их, я знаю как минимум два способа, которые обеспечат это. Я тестировал только второй, но считаю, что оба работают одинаково.

Если вы используете @Bean, вы можете ссылаться на initMethod, например.

@Configuration
public class BeanConfiguration {

  @Bean(initMethod="init")
  public BeanA beanA() {
    return new BeanA();
  }
}

public class BeanA {

  // method to be initialized after context is ready
  public void init() {
  }

} 

Если вы используете @Component, вы можете аннотировать @EventListener следующим образом.

@Component
public class BeanB {

  @EventListener
  public void onApplicationEvent(ContextRefreshedEvent event) {
  }
}

В моем случае у меня есть устаревшая система, в которой я сейчас использую IoC / DI, где Spring Boot - это выбранный фреймворк. Старая система привносит в таблицу множество циклических зависимостей, и поэтому я должен часто использовать сеттер-зависимости. Это вызвало у меня головную боль, поскольку я не мог доверять @PostConstruct, поскольку автоматическое подключение / инъекция сеттером еще не было выполнено. Порядок - конструктор, @PostConstruct, затем автоматические сеттеры. Я решил это с помощью аннотации @EventListener, которая будет запускаться последней и в «одно и то же» время для всех beans. В примере также показана реализация InitializingBean.

У меня есть два класса (@Component), которые зависят друг от друга. В этом примере классы выглядят одинаково, отображая только один из них.

@Component
public class BeanA implements InitializingBean {
  private BeanB beanB;

  public BeanA() {
    log.debug("Created...");
  }

  @PostConstruct
  private void postConstruct() {
    log.debug("@PostConstruct");
  }

  @Autowired
  public void setBeanB(BeanB beanB) {
    log.debug("@Autowired beanB");
    this.beanB = beanB;
  }

  @Override
  public void afterPropertiesSet() throws Exception {
    log.debug("afterPropertiesSet()");
  }

  @EventListener
  public void onApplicationEvent(ContextRefreshedEvent event) {
    log.debug("@EventListener");
  } 
}

Это вывод журнала, показывающий порядок вызовов при запуске контейнера.

2018-11-30 18:29:30.504 DEBUG 3624 --- [           main] com.example.demo.BeanA                   : Created...
2018-11-30 18:29:30.509 DEBUG 3624 --- [           main] com.example.demo.BeanB                   : Created...
2018-11-30 18:29:30.517 DEBUG 3624 --- [           main] com.example.demo.BeanB                   : @Autowired beanA
2018-11-30 18:29:30.518 DEBUG 3624 --- [           main] com.example.demo.BeanB                   : @PostConstruct
2018-11-30 18:29:30.518 DEBUG 3624 --- [           main] com.example.demo.BeanB                   : afterPropertiesSet()
2018-11-30 18:29:30.518 DEBUG 3624 --- [           main] com.example.demo.BeanA                   : @Autowired beanB
2018-11-30 18:29:30.518 DEBUG 3624 --- [           main] com.example.demo.BeanA                   : @PostConstruct
2018-11-30 18:29:30.518 DEBUG 3624 --- [           main] com.example.demo.BeanA                   : afterPropertiesSet()
2018-11-30 18:29:30.607 DEBUG 3624 --- [           main] com.example.demo.BeanA                   : @EventListener
2018-11-30 18:29:30.607 DEBUG 3624 --- [           main] com.example.demo.BeanB                   : @EventListener

Как видите, @EventListener запускается последним после того, как все будет готово и настроено.

Avec
источник
-2
public class InitHelloWorld implements BeanPostProcessor {

   public Object postProcessBeforeInitialization(Object bean,
             String beanName) throws BeansException {
       System.out.println("BeforeInitialization : " + beanName);
       return bean;  // you can return any other object as well
   }

   public Object postProcessAfterInitialization(Object bean,
             String beanName) throws BeansException {
       System.out.println("AfterInitialization : " + beanName);
       return bean;  // you can return any other object as well
   }

}
Ясир Шабир Чоудхари
источник