Metoda init w Spring Controller (wersja adnotacji)

105

Konwertuję kontroler na nowszą wersję adnotacji. W starej wersji użyłem metody init w springmvc-servlet.xml używając:

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

Jak mogę określić metodę init przy użyciu wersji adnotacji?

Krt_Malta
źródło
Zobacz także stackoverflow.com/questions/1088550
skaffman

Odpowiedzi:

238

Możesz użyć

@PostConstruct
public void init() {
   // ...
}
Johan Sjöberg
źródło
1
Masz rację, jego „Wspólne adnotacje 1.0”, Java 1.7 również będzie działać.
Ponury
Jeśli musisz użyć użytkownika z SecurityContextHolder, w momencie PostConstruct nie jest on zainicjowany. Musi być używany jak metoda bezstanowa. (getUser () ... {return Security ... user ();}
Joao Polo
publiczne lub prywatne
anshulkatta
20

Alternatywnie możesz mieć swoją klasę zaimplementowaną w InitializingBeaninterfejsie w celu zapewnienia funkcji zwrotnej ( afterPropertiesSet()), którą ApplicationContext będzie wywoływać podczas konstruowania komponentu bean.

matowe b
źródło
4

Wiosną proces inicjalizacji można przechwycić na kilka sposobów. Jeśli musisz zainicjować wszystkie ziarna i automatycznie je podłączyć / wstrzyknąć, są co najmniej dwa znane mi sposoby, które to zapewnią. Testowałem tylko drugi, ale wierzę, że oba działają tak samo.

Jeśli używasz @Bean, możesz odwoływać się przez initMethod, w ten sposób.

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

} 

Jeśli używasz @Component, możesz dodawać adnotacje za pomocą @EventListener w ten sposób.

@Component
public class BeanB {

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

W moim przypadku mam starszy system, w którym teraz używam IoC / DI, gdzie Spring Boot jest wybranym frameworkiem. Stary system wprowadza wiele zależności cyklicznych do tabeli, dlatego muszę często używać zależności ustawiających. To przyprawiło mnie o ból głowy, ponieważ nie mogłem zaufać @PostConstruct, ponieważ automatyczne podłączanie / wstrzykiwanie przez setter nie zostało jeszcze wykonane. Kolejność to konstruktor, @PostConstruct, a następnie autowired setters. Rozwiązałem to za pomocą adnotacji @EventListener, która będzie działać jako ostatnia i „w tym samym” czasie dla wszystkich fasoli. Przykład pokazuje również implementację InitializingBean.

Mam dwie klasy (@Component) z zależnościami od siebie. Klasy wyglądają tak samo na potrzeby tego przykładu, wyświetlając tylko jedną z nich.

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

To jest dane wyjściowe dziennika przedstawiające kolejność wywołań podczas uruchamiania kontenera.

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

Jak widać, @EventListener jest uruchamiane jako ostatnie, gdy wszystko jest gotowe i skonfigurowane.

Avec
źródło
-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
źródło