127 votes

Méthode Init dans le contrôleur Spring (version annotation)

Je suis en train de convertir un contrôleur à la nouvelle version d'annotation. Dans l'ancienne version, j'avais l'habitude de spécifier la méthode init dans springmvc-servlet.xml en utilisant :

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

Comment puis-je spécifier la méthode init en utilisant la version d'annotation ?

0 votes

287voto

Johan Sjöberg Points 20759

Vous pouvez utiliser

@PostConstruct
public void init() {
   // ...
}

1 votes

Vous avez raison, il s'agit de "Common Annotations 1.0", Java1.7 fonctionnera également.

0 votes

Si vous devez utiliser l'utilisateur du SecurityContextHolder, il n'est pas initialisé au moment de la post-construction. Il faut donc l'utiliser comme une méthode sans état. (getUser()... { return Security...user() ; }

0 votes

Public ou privé

22voto

matt b Points 73770

Vous pouvez également demander à votre classe d'implémenter la méthode InitializingBean pour fournir une fonction de rappel ( afterPropertiesSet() ) que l'ApplicationContext invoquera lorsque le bean sera construit.

13voto

Ronny Points 108

Il existe plusieurs façons d'intercepter le processus d'initialisation dans Spring. Si vous devez initialiser tous les beans et les auto-câbler/injecter, il y a au moins deux méthodes que je connais qui permettent de le faire. Je n'ai testé que la seconde mais je pense que les deux fonctionnent de la même manière.

Si vous utilisez @Bean, vous pouvez faire référence à initMethod, comme ceci.

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

} 

Si vous utilisez @Component, vous pouvez annoter @EventListener comme suit.

@Component
public class BeanB {

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

Dans mon cas, j'ai un ancien système pour lequel j'utilise maintenant IoC/DI et Spring Boot est le framework choisi. L'ancien système apporte beaucoup de dépendances circulaires et je dois donc utiliser beaucoup de setter-dependency. Cela m'a donné quelques maux de tête car je ne pouvais pas faire confiance à @PostConstruct puisque l'autowiring/injection par setter n'était pas encore fait. L'ordre est le suivant : constructeur, @PostConstruct puis setter autowired. J'ai résolu le problème avec l'annotation @EventListener qui s'exécute en dernier et au même moment pour tous les beans. L'exemple montre également l'implémentation de InitializingBean.

J'ai deux classes (@Component) qui dépendent l'une de l'autre. Les classes sont identiques pour les besoins de cet exemple qui n'en affiche qu'une seule.

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

Voici la sortie du journal montrant l'ordre des appels au démarrage du conteneur.

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

Comme vous pouvez le voir, @EventListener est exécuté en dernier lieu, une fois que tout est prêt et configuré.

1voto

cooooopd Points 1

@PostConstruct、implementer InitializingBean、specify init-method they have call orders. Vous ne pouvez donc pas les utiliser pour remplacer init-method. Vous pouvez essayer ceci :

@Bean(initMethod = "init")
public MyBean mybean() {
    return new MyBean();
}

class MyBean {
public void init() {
    System.out.println("MyBean init");
}

}

dans votre classe, vous pouvez déclarer une méthode nommée init().

Se référer à : https://docs.spring.io/spring-framework/docs/current/reference/html/core.html#:~:text=Multiples%20cycles%20mécanismes%20configurés%20pour%20le%20même%20carottier%2C%20avec%20différentes%20méthodes%2C%20d'initialisation%20sont%20appelés%20comme%20les%20suivants%3A

-2voto

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
   }

}

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X