Bean 초기화가 완료된 후 메소드를 호출하는 방법은 무엇입니까?


237

ApplicationContext 가로 드 될 때 Bean에서 (정적이 아닌) 메소드를 한 번만 호출 해야하는 유스 케이스가 있습니다. MethodInvokingFactoryBean을 사용하면 괜찮습니까? 아니면 더 나은 해결책이 있습니까?

참고로 ConfigContextLoaderListener를 사용하여 웹 응용 프로그램에 응용 프로그램 컨텍스트를로드합니다. 빈 'A'가 인스턴스화되면 methodA ()를 한 번만 호출하십시오.

어떻게하면 잘할 수 있습니까?

답변:


196

다음과 같은 것을 사용할 수 있습니다.

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

Bean이 인스턴스화 될 때 "init"메소드를 호출합니다.


15
postConstruct는 스프링 빈 초기화를 망쳐 놓지 않기 때문에 대부분의 경우 더 좋을 것입니다.
lwpro2

4
@ lwpro2 여기에서 "스프링 빈 초기화를 망치고 싶지 않다"는 것은 무슨 뜻입니까?
Yngve Sneen Lindal

@Mercer Traieste 여기에 클래스 속성에 무엇을 주어야합니까? 여기에 컨트롤러 클래스를 줄 수 있습니까?
KJEjava48

314

다른 답변에서 @PostConstruct 제안을 확장하려면 이것이 실제로 가장 좋은 해결책이라고 생각합니다.

  • 코드를 Spring API에서 분리합니다 (@PostConstruct는 javax. *).
  • Bean을 초기화하기 위해 호출 해야하는 것으로 init 메소드에 명시 적으로 주석을 달았습니다.
  • 스프링 빈 정의에 init-method 속성을 추가 할 필요가 없습니다. 스프링은 자동으로 메소드를 호출합니다 (어쨌든 어노테이션에서 어노테이션 구성 옵션을 등록한다고 가정).

9
고마워, 이것은 작동합니다. Spring과 함께 사용하려면 CommonAnnotationBeanPostProcessor bean을 등록하기 위해 "<context : annotation-config />"를 포함시켜야합니다.
khylo

2
적합한 <context:component-scan>것도 작동하며 클래스 경로에 Spring이 아닌 큰 라이브러리가있는 경우 시작 시간을 줄이는 데 유용 할 수 있습니다.
Donal Fellows

5
PostConstruct 용 JavaDoc에 따르면 클래스 당 하나의 메소드에만 주석을 달 수 있습니다. docs.oracle.com/javaee/5/api/javax/annotation/…
Andrew Swan

@PostConstruct는 트랜잭션 관리자와 함께 작동하지 않습니다. forum.spring.io/forum/spring-projects/data/…
mmm

2
@PostConstruct는 인스턴스화하는 Bean이 자신의 클래스가 아닌 제 3 자 클래스 인 경우에도 많이 사용되지 않습니다.
John Rix

102

참고 문헌에 설명 된 것처럼 고려해야 할 세 가지 접근법이 있습니다.

init-method 속성 사용

장점 :

  • 인터페이스를 구현하기 위해 Bean이 필요하지 않습니다.

단점 :

  • Bean이 올바르게 구성되었는지 확인하기 위해 구성 후에이 방법이 필요하지 않습니다.

InitializingBean 구현

장점 :

  • init-method를 지정하거나 구성 요소 스캐닝 / 주석 처리를 켤 필요가 없습니다.
  • 라이브러리와 함께 제공되는 Bean에 적합합니다.이 라이브러리를 사용하는 응용 프로그램이 Bean 라이프 사이클과 관련되지 않도록합니다.

단점 :

  • init-method 방식보다 더 침습적입니다.

JSR-250 @PostConstruct lifecyle 주석 사용

장점 :

  • 컴포넌트 스캔을 사용하여 Bean을 자동 감지 할 때 유용합니다.
  • 초기화에 특정 방법을 사용해야한다는 것을 분명히합니다. 의도는 코드에 더 가깝습니다.

단점 :

  • 구성에서 초기화가 더 이상 중앙에서 지정되지 않습니다.
  • 주석 처리를 설정해야합니다 (이따금 잊을 수 있음)

4
@PostConstruct초기화 처리가 끝나면 호출하는 메소드가 필요한 클래스의 일부이기 때문에 실제로 정확하게 사용하는 것이 좋습니다 .
Donal Fellows

그 클래스가 정말로 그것을 필요로하고 생성자에서 그것을 할 수 없다면, 그것을 코드 냄새라고 생각합니다.
user482745

39

구현을 시도 했습니까 InitializingBean? 당신이 쫓는 것과 똑같습니다.

단점은 bean이 Spring을 인식하지만 대부분의 응용 프로그램에서는 그렇게 나쁘지 않다는 것입니다.


2
XML에서 init-method를 지정하는 것보다 인터페이스 구현을 선택하는 이유가 있습니까?
Mark

4
그것은 맛의 문제입니다. 이 인터페이스는 Spring 컴포넌트 모델의 일부이며, 그 목적을 위해서만 사용되며, 커스텀 명명 된 메소드의 경우 컴포넌트 라이프 사이클을 완료하기 위해 호출해야하는 것은 분명하지 않을 수 있습니다. 그래서 이것은 주로 의사 소통을합니다. 물론 스프링 프레임 워크에 도입 된 종속성의 단점이 있습니다. 그 사이에 좋은 방법은 @PostConstruct를 사용하는 것인데, 명확한 의미론을 가지고 있지만 의존성을 도입하지는 않습니다.
Oliver Drotbohm

7
Oliver는 나에게 멋진 변명을 주지만 실제로는 init-method에 대해 잊어 버렸습니다. 근본적으로 뭔가 해야 구성에합니다.
Jon Skeet

8

애플리케이션 컨텍스트에 사용자 정의 BeanPostProcessor 를 배치하여 이를 수행 할 수 있습니다. 또는 Bean에서 Spring 인터페이스를 구현하는 것이 마음에 들지 않으면 InitializingBean 인터페이스 또는 "init-method"지시문 (동일한 링크)을 사용할 수 있습니다.


누구나 BeanPostProcessor 작성 방법에 대한 세부 정보를 가지고 있습니다. 그게 내가 필요한 것 같습니다. 건배 :)
peakit

봄에는 많은 예가 있습니다. BeanPostProcessor 용 JavaDoc API를 보면 많은 구현 클래스에 대한 링크를 찾을 수 있습니다. 그런 다음 소스 코드를보십시오.
Rob H

-7

두 가지 접근 방식에 대한 혼란, 즉

  1. @PostConstruct
  2. init-method="init"

개인적인 경험을 통해 (1) 서블릿 컨테이너에서만 작동하고 (2) 데스크탑 환경에서도 모든 환경에서 작동한다는 것을 깨달았습니다. 따라서 독립형 애플리케이션에서 Spring을 사용하려면 (2)를 사용하여 "초기화 후이 메소드를 호출해야합니다.


4
기술적으로 @PostConstruct(Spring 기반 앱에서 사용되는 경우) 소유하는 Spring 컨텍스트의 수명과 관련이 있습니다. 이러한 컨텍스트는 모든 종류의 응용 프로그램에서 사용할 수 있습니다.
Donal Fellows

그것은 내가 기대했던 행동이지만 나를 위해 작동하지 않았습니다.
Ayorinde
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.