본문 바로가기

Web/spring

[Spring Framework core] 1.6. Customizing the Nature of a Bean (2)

728x90

https://docs.spring.io/spring-framework/docs/current/reference/html/core.html#beans-factory-lifecycle-disposablebean

 

Core Technologies

In the preceding scenario, using @Autowired works well and provides the desired modularity, but determining exactly where the autowired bean definitions are declared is still somewhat ambiguous. For example, as a developer looking at ServiceConfig, how do

docs.spring.io

 

틀린 해석이 있다면 알려주세요 ☘️

 

 

 


Default Initialization and Destroy Methods ~ Shutting Down the Spring IoC Container Gracefully in Non-Web Applications

 

Spring 고유의 InitializingBean 및 DisposableBean Callback interface를 사용하지않는 initialization, destroy 메소드 콜백을 작성할 때는 일반적으로 init(), initialize(), dispose() 등의 이름으로 작성한다. 이러한 life cycle callback method 이름이 표준화되면 일관성을 보장받을 수 있다.

 

명명된 initialization 를 찾아 모든 bean에서 콜백 메소드 이름을 삭제하도록 spring container를 구성할수도 있다. 

 without having to configure an init-method="init" attribute with each bean definition.

Spring IoC 컨테이너는 bean이 생성될 때 (life cycle 표준콜백에 따라) 메서드를 호출한다

이 기능은 initialization, destroy 메소드 콜백에 대해 일관된 명명 규칙을 적용시켜준다

 

 

public class DefaultBlogService implements BlogService {

    private BlogDao blogDao;

    public void setBlogDao(BlogDao blogDao) {
        this.blogDao = blogDao;
    }

    // this is (unsurprisingly) the initialization callback method
    public void init() {
        if (this.blogDao == null) {
            throw new IllegalStateException("The [blogDao] property must be set.");
        }
    }
}

그런 다음 다음과 유사한 빈에서 해당 클래스를 사용할 수 있다.

<beans default-init-method="init">

    <bean id="blogService" class="com.something.DefaultBlogService">
        <property name="blogDao" ref="blogDao" />
    </bean>

</beans>

The presence of the default-init-method attribute on the top-level <beans/> element attribute causes the Spring IoC container to recognize a method called init on the bean class as the initialization method callback. When a bean is created and assembled, if the bean class has such a method, it is invoked at the appropriate time.

You can configure destroy method callbacks similarly (in XML, that is) by using the default-destroy-method attribute on the top-level <beans/> element.

Where existing bean classes already have callback methods that are named at variance with the convention, you can override the default by specifying (in XML, that is) the method name by using the init-method and destroy-method attributes of the <bean/> itself.

 

 

Spring container는 bean이 모든 종속성과 함께 제공된 직후 구성된 initialization callback 호출을 보장한다

initialization 콜백은 원시 bean 참조에서 호출되며, 이는 AOP 인터셉터 등이 아직 해당 빈에 적용되지 않았다는 것을 의미한다

그러니까, 대상 빈이 먼저 완전히 생성이 되면, 인터셉터 체인에 있는 AOP가 적용된다는 것이다

대상 bean과 프록시가 별도로 정의된 경우에 프록시 적용 안되고 원시 대상 bean으로 작용할 수 있다

>>  인터셉터에 init 메서드를 를 적용하는 하는 것은 일관성 없는 코드가 만들어질 수 있다

 

 

 

 

Combining Lifecycle Mechanisms

라이프사이클 제어를 위한 3가지 옵션이다

As of Spring 2.5, you have three options for controlling bean lifecycle behavior:

 

Bean에 대해 여러 라이프사이클 메커니즘이 구성되고 각 메커니즘이 다른 메소드 이름으로 구성된 경우 구성된 각 메소드는 이 참고 사항 다음에 나열된 순서대로 실행된다. 그러나 이러한 수명 주기 메커니즘 중 둘 이상에 대해 동일한 메서드 이름(예: init()초기화 메서드용)이 구성된 경우 해당 메서드는 한 번 실행된다 .

 

서로 다른 초기화 방법을 사용하여 동일한 bean에 대해 구성된 lifecycle 의 메커니즘은 이렇게 호출된다

  1. Methods annotated with @PostConstruct
  2. afterPropertiesSet() as defined by the InitializingBean callback interface
  3. A custom configured init() method

 

destroy는 이렇게

  1. Methods annotated with @PreDestroy
  2. destroy() as defined by the DisposableBean callback interface
  3. A custom configured destroy() method

 

Startup and Shutdown Callbacks

The Lifecycle interface defines the essential methods for any object that has its own lifecycle requirements (such as starting and stopping some background process):

public interface Lifecycle {

    void start();

    void stop();

    boolean isRunning();
}
 

 

 

모든 Spring object는 lifecycle 인터페이스를 구현할 수 있다.

Any Spring-managed object may implement the Lifecycle interface. Then, when the ApplicationContext itself receives start and stop signals (for example, for a stop/restart scenario at runtime), it cascades those calls to all Lifecycle implementations defined within that context. It does this by delegating to a LifecycleProcessor, shown in the following listing:

 

public interface LifecycleProcessor extends Lifecycle {

    void onRefresh();

    void onClose();
}
 

Notice that the LifecycleProcessor is itself an extension of the Lifecycle interface. It also adds two other methods for reacting to the context being refreshed and closed.

 

 

일반 org.springframework.context.Lifecycle 인터페이스는 명시적인 시작 및 중지 알림에 대한 일반 계약이며 컨텍스트 새로 고침 시간에 자동 시작을 의미하지 않는다다.

특정 빈(시작 단계 포함)의 자동 시작에 대한 세밀한 제어를 위해서는 org.springframework.context.SmartLifecycle 를 사용해야한다.

또한 중지 알림이 파기 전에 오는 것을 보장하지 않는다.

일반적인 종료 시 모든 수명 주기 빈은 일반 파괴 콜백이 전파되기 전에 먼저 중지 알림을 받는다. 그러나 컨텍스트 수명 동안의 갓 새로고침 또는 중지된 새로 고침 시도에서는 destory 메서드만 호출된다.

 

 

 

 

시작이나 종료되는 순서가 중요할 수 있다

두 객체 사이에 depends-on(종속) 관계가 있는 경우에는 종속되어있는 쪽은 종속한 항목 이후에 시작하고, 그 전에 중지해야한다. 이러한 직접적인 종속성을 알 수 없을 경우가 있는데, 특정 유형의 개체가 다른 유형의 개체보다 먼저 시작해야한다는 점만 알 수 있다.

이럴때 SmartLifecycle 인터페이스를 사용하면 된다. 이는 상위 인터페이스인 Phased에 정의된 getPhase()라는 메서드를 정의로 다른 옵션을 정의할 수 있다.

 

public interface Phased {

    int getPhase();
}
 

The following listing shows the definition of the SmartLifecycle interface:

public interface SmartLifecycle extends Lifecycle, Phased {

    boolean isAutoStartup();

    void stop(Runnable callback);
}
 
 
시작할 때는 단계가 가장 낮은 개체가 먼저 시작된다. 정지할 때는 그 역순이다.
SmartLifecycle 을 구현하고 getPhase() 메소드가 Integer.MIN_VALUE를 반환하는 개체는 가장 먼저 시작되어 마지막으로 중지된다는 뜻이다. Integer.MAX_VALUE 는 그 반대. 단계 값을 고려했을때 SmartLifeCycle을 구현하지 않는 보통의 수명 주기 개체의 기본 단계는 0이다. 따라서 음수일 수록 먼저 시작하고, 양수일 수록 늦게 시작한다는 뜻이다
SmartLifecycle에 의해 정의된 중지 메소드는 콜백을 허용해준다. 모든 구현은 구현 종료 프로세스가 완료 된 후 해당 콜백의 run() 메소드를 호출해야한다. LifecycleProcessor 인터페이스의 기본 구현인 DefaultLifecycleProcessor가 해당 콜백을 호출하기 위해 각 단계 내의 개체 그룹에 대한 제한 시간 값까지 대기하므로 필요한 경우 비동기식 종료가 가능하다. 단계별 기본 제한 시간은 30초이다.
컨텍스트 내에서 lifecycleProcessor라는 빈을 정의하여 기본 수명 주기 프로세서 인스턴스를 재정의할 수 있다. 제한 시간만 수정하려는 경우 다음을 정의하면 충분하다
 
<bean id="lifecycleProcessor" class="org.springframework.context.support.DefaultLifecycleProcessor">
    <!-- timeout value in milliseconds -->
    <property name="timeoutPerShutdownPhase" value="10000"/>
</bean>
 

LifecycleProcessor 인터페이스는 컨텍스트를 새로 고치고 닫기 위한 콜백 메서드도 정의한다. 후자는 stop()이 명시적으로 호출된 것처럼 종료 프로세스를 구동하지만 컨텍스트가 닫힐 때 발생한다. 반면에 '새로 고침' 콜백은 SmartLifecycle 빈의 또 다른 기능을 활성화한다.

컨텍스트가 새로 고쳐지면(모든 개체가 인스턴스화되고 초기화된 후) 해당 콜백이 호출된다.

이 시점에서 기본 수명 주기 프로세서는 각 SmartLifecycle 객체의 isAutoStartup() 메서드에서 반환된 bool 값을 확인한다.

true인 경우 해당 객체는 컨텍스트 또는 자체 start() 메서드의 명시적 호출을 기다리지 않고 해당 지점에서 시작한다(컨텍스트 새로 고침과 달리 컨텍스트 시작은 표준 컨텍스트 구현에 대해 자동으로 발생하지 않음).

단계 값과 모든 "종속" 관계는 앞에서 설명한 대로 시작 순서를 결정한다.

 

 

Shutting Down the Spring IoC Container Gracefully in Non-Web Applications

** 이건 읽기만 하고 넘어감

This section applies only to non-web applications. Spring’s web-based ApplicationContext implementations already have code in place to gracefully shut down the Spring IoC container when the relevant web application is shut down.
 

If you use Spring’s IoC container in a non-web application environment (for example, in a rich client desktop environment), register a shutdown hook with the JVM. Doing so ensures a graceful shutdown and calls the relevant destroy methods on your singleton beans so that all resources are released. You must still configure and implement these destroy callbacks correctly.

To register a shutdown hook, call the registerShutdownHook() method that is declared on the ConfigurableApplicationContext interface, as the following example shows:

public final class Boot {

    public static void main(final String[] args) throws Exception {
        ConfigurableApplicationContext ctx = new ClassPathXmlApplicationContext("beans.xml");

        // add a shutdown hook for the above context...
        ctx.registerShutdownHook();

        // app runs here...

        // main method exits, hook is called prior to the app shutting down...
    }
}
 

 

 

728x90