Spring/Spring

[Spring][Core] 2-8. Bean: Customizing the Nature of a Bean

noahkim_ 2023. 10. 14. 23:51

1. Lifecycle Callbacks

  • Spring은 빈의 생명주기와 상호작용할 수 있는 여러 방법을 제공합니다.
  • 이러한 도구를 활용하여 빈의 초기화 및 파괴 과정에 사용자 지정 동작을 추가할 수 있습니다.

 

BeanPostProcessor 인터페이스

  • 빈 생성 시기에 BeanFactory Hook을 정의하는 인터페이스 입니다.
  • 내부적으로 콜백 인터페이스를 찾아 적절한 메서드를 호출하기 위해 BeanPostProcessor를 사용합니다.
  • 생성 전/후의 콜백함수를 정의할 수 있습니다.
    • postProcessBeforeInitialization(), postProcessAfterInitialization()

 

Initialization Callbacks

  • 초기화 메서드는 컨테이너의 싱글톤 생성 잠금 내에서 실행됩니다.
  • 여러 스레드가 동시에 호출하려는 시도를 방지합니다.

 

InitializingBean 인터페이스
  • BeanFactory의 빈 초기화 후, 특정 작업을 수행하도록 하는 인터페이스 입니다.
public class AnotherExampleBean implements InitializingBean {

    @Override
    public void afterPropertiesSet() {
        // do some initialization work
    }
}

 

@PreConstruct (JSR-250)
  • 현대 Spring 응용 프로그램에서 생명주기 콜백을 받는 가장 권장되는 방법입니다.
  • 어노테이션을 사용하면 빈들이 Spring 특정 인터페이스에 종속되지 않습니다.
@Component
public class BookService {

    private List<Book> books;

    @PreConstruct
    public void initialize() {
        // 빈 초기화 로직
        books = new ArrayList<>();
        books.add(new Book("Spring in Action"));
        books.add(new Book("Effective Java"));
        System.out.println("BookService initialized!");
    }
}

 

 

init-method (xml)
  • JSR-250 어노테이션을 사용하고 싶지 않지만 인터페이스에 종속되고 싶지 않을 때 사용하는 방법입니다.
  • 빈 정의 메타데이터의 init-method 를 작성합니다.
<bean id="exampleInitBean" class="examples.ExampleBean" init-method="init"/>
public class ExampleBean {

    public void init() {
        // do some initialization work
    }
}

 

Destruction Callbacks

DisposableBean
  • BeanFactory의 빈 제거 후, 특정 작업을 수행하도록 하는 인터페이스
public class AnotherExampleBean implements DisposableBean {

    @Override
    public void destroy() {
        // do some destruction work (like releasing pooled connections)
    }
}

 

@PostDestroy (JSR-250)
@Component
public class DatabaseConnectionService {

    private Connection connection;

    @PostDestroy
    public void cleanup() {
        // 연결 해제 로직
        if (connection != null) {
            connection.close();
            System.out.println("Database connection closed!");
        }
    }
}

 

destroy-method (xml)
<bean id="exampleDestructionBean" class="examples.ExampleBean" destroy-method="cleanup"/>
public class ExampleBean {

    public void cleanup() {
        // do some destruction work (like releasing pooled connections)
    }
}

  

2. Startup and Shutdown Callbacks

Lifecycle 인터페이스

  • 빈의 생명주기를 관리하기 위한 메서드를 정의합니다. (백그라운드 프로세스 시작 및 중지)
public interface Lifecycle {
    void start();
    void stop();
    boolean isRunning();
}

 

start()
  • 빈 시작시 실행되는 로직을 정의합니다.

 

stop()
  • 빈 종료시 실행되는 로직을 정의합니다.
  • destroy 메서드가 호출되기 전에 먼저 실행됩니다.
  • 빈이 완전히 종료되기 전에 필요한 처리나 정리 작업을 수행할 수 있습니다.

 

isRunning()
  • 객체가 현재 실행 중인지 확인합니다. 

 

LifecycleProcessor 인터페이스

  • Lifecycle의 확장 버전
  • ApplicationContext가 새로 고침되거나 닫힐 때 반응하는 두 가지 추가 메서드를 포함합니다.
public interface LifecycleProcessor extends Lifecycle {
    void onRefresh();
    void onClose();
}

 

onRefresh()
  • ApplicationContext새로 고쳐질 때 호출됩니다.

 

onClose()
  • ApplicationContext종료될 때 호출됩니다.

 

Phased 인터페이스

  • 생명주기 동안 컴포넌트의 시작 및 종료 순서를 정의하기 위해 사용되는 인터페이스입니다.
public interface Phased {
    int getPhase();	
}

 

getPhase()
  • 현재 객체의 단계 값을 반환합니다.

 

SmartLifecycle 인터페이스

  • Lifecycle과 Phased를 확장하여, 자동 시작 여부와 비동기적인 종료를 위한 추가적인 기능을 제공합니다.
  • 값이 낮을수록 먼저 시작됩니다.
  • 값이 낮을수록 나중에 종료됩니다.
public interface SmartLifecycle extends Lifecycle, Phased {
    boolean isAutoStartup();
    void stop(Runnable callback);
}

 

isAutoStartup()
  • 객체가 자동으로 시작되어야 하는지 여부를 반환합니다.
  • true이면start() 메서드의 명시적 호출을 기다리지 않고 자동으로 시작됩니다.

 

stop(Runnable callback)
  • 비동기적인 종료하는데 사용됩니다.
  • 종료 프로세스가 완료되면 콜백의 run() 메서드를 호출합니다.

 

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

  • Spring IoC 컨테이너를 웹이 아닌 애플리케이션에서 사용할 때의 안전한 종료 방법을 제공합니다.
  • 종료 후크를 등록함으로써 시스템이 안전하게 종료됩니다.
  • 싱글톤 빈에 정의된 destroy 메서드들이 호출되어 모든 리소스가 정상적으로 해제됩니다.
  • 만약 웹 환경이 아닌 다른 환경에서 Spring의 IoC 컨테이너를 사용한다면 JVM에 종료 후크(shutdown hook)를 등록해야 합니다.
  • ConfigurableApplicationContext 인터페이스에 정의된 registerShutdownHook() 메서드를 호출합니다.
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...
    }
}

 

ApplicationContextAware and BeanNameAware

ApplicationContextAware
public interface ApplicationContextAware {
    void setApplicationContext(ApplicationContext applicationContext) throws BeansException;
}
  • 해당 객체를 생성한 ApplicationContext에 대한 참조를 제공받습니다.
  • 빈이 이 메서드를 통해 자신을 생성한 ApplicationContext의 참조를 얻게 됩니다.

 

BeanNameAware
public interface BeanNameAware {
    void setBeanName(String name) throws BeansException;
}
  • 해당 클래스에 정의된 객체 이름에 대한 참조를 제공받습니다.
  • 일반적인 빈 속성이 채워진 후 - 초기화 콜백 전에 호출됩니다.

 

 

 

출처