Método de inicio en Spring Controller (versión de anotación)

105

Estoy convirtiendo un controlador a la versión de anotación más nueva. En la versión anterior, solía especificar el método init en springmvc-servlet.xml usando:

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

¿Cómo puedo especificar el método init usando la versión de anotación?

Krt_Malta
fuente
Véase también stackoverflow.com/questions/1088550
skaffman

Respuestas:

238

Puedes usar

@PostConstruct
public void init() {
   // ...
}
Johan Sjöberg
fuente
1
Tiene razón, su "Common Annotations 1.0", Java1.7 también funcionará.
Grim
Si necesita utilizar el usuario de SecurityContextHolder, en el momento de PostConstruct no se inicializa. Debe usarse como un método sin estado. (getUser () ... {return Security ... user ();}
Joao Polo
público o privado
anshulkatta
20

Alternativamente, puede hacer que su clase implemente la InitializingBeaninterfaz para proporcionar una función de devolución de llamada ( afterPropertiesSet()) que ApplicationContext invocará cuando se construya el bean.

mate b
fuente
4

Hay varias formas de interceptar el proceso de inicialización en Spring. Si tiene que inicializar todos los beans y conectarlos automáticamente / inyectarlos, hay al menos dos formas que conozco que asegurarán esto. Solo he probado el segundo, pero creo que ambos funcionan igual.

Si está utilizando @Bean, puede hacer referencia mediante initMethod, así.

@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 está utilizando @Component, puede anotar con @EventListener de esta manera.

@Component
public class BeanB {

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

En mi caso, tengo un sistema heredado en el que ahora estoy usando IoC / DI donde Spring Boot es el marco elegido. El sistema antiguo trae muchas dependencias circulares a la tabla y, por lo tanto, debo usar mucho la dependencia del setter. Eso me dio algunos dolores de cabeza ya que no podía confiar en @PostConstruct ya que aún no se había realizado el cableado automático / inyección por parte del colocador. El orden es constructor, @PostConstruct y luego configuradores con cableado automático. Lo resolví con la anotación @EventListener que se ejecutará en último lugar y al "mismo" tiempo para todos los beans. El ejemplo también muestra la implementación de InitializingBean.

Tengo dos clases (@Component) con dependencia entre sí. Las clases tienen el mismo aspecto para el propósito de este ejemplo que muestra solo una de ellas.

@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 es la salida del registro que muestra el orden de las llamadas cuando se inicia el contenedor.

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 puede ver, @EventListener se ejecuta en último lugar después de que todo esté listo y configurado.

Avec
fuente
-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
fuente