Método Init no Spring Controller (versão de anotação)

105

Estou convertendo um controlador para a versão de anotação mais recente. Na versão anterior, eu costumava especificar o método init em springmvc-servlet.xml usando:

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

Como posso especificar o método init usando a versão de anotação?

Krt_Malta
fonte
Consulte também stackoverflow.com/questions/1088550
skaffman

Respostas:

238

Você pode usar

@PostConstruct
public void init() {
   // ...
}
Johan Sjöberg
fonte
1
Você está certo, seu "Common Annotations 1.0", Java1.7 também funcionará.
Grim
Se você precisa usar o usuário de SecurityContextHolder, no momento PostConstruct ele não é inicializado. Ele precisa ser usado como um método sem estado. (getUser () ... {return Security ... user ();}
João Polo
público ou privado
anshulkatta
20

Alternativamente, você pode fazer com que sua classe implemente a InitializingBeaninterface para fornecer uma função de retorno de chamada ( afterPropertiesSet()) que o ApplicationContext invocará quando o bean for construído.

matt b
fonte
4

Existem várias maneiras de interceptar o processo de inicialização no Spring. Se você tiver que inicializar todos os beans e autowire / injetá-los, há pelo menos duas maneiras que conheço que garantirão isso. Eu testei apenas o segundo, mas acredito que ambos funcionam da mesma forma.

Se você estiver usando @Bean, você pode fazer referência por initMethod, como este.

@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() {
  }

} 

Se estiver usando @Component, você pode anotar com @EventListener assim.

@Component
public class BeanB {

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

No meu caso, tenho um sistema legado onde agora estou usando IoC / DI, onde Spring Boot é a estrutura escolhida. O sistema antigo traz muitas dependências circulares para a tabela e, portanto, devo usar muito a dependência de setter. Isso me deu algumas dores de cabeça, já que não podia confiar em @PostConstruct, já que o autowiring / injeção por setter ainda não estava feito. O pedido é construtor, @PostConstruct e configuradores autowired. Resolvi isso com a anotação @EventListener que será executada por último e "ao mesmo" tempo para todos os beans. O exemplo mostra a implementação de InitializingBean também.

Eu tenho duas classes (@Component) com dependência uma da outra. As classes parecem iguais para o propósito deste exemplo, exibindo apenas uma delas.

@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");
  } 
}

Esta é a saída do log que mostra a ordem das chamadas quando o contêiner é iniciado.

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

Como você pode ver, @EventListener é executado por último depois que tudo estiver pronto e configurado.

Avec
fonte
-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
   }

}
Yasir Shabbir Choudhary
fonte