-
[Spring] Bean Life Cycle / Scope / Profiles / ApplicationContextDEV/Spring 2024. 5. 17. 15:52
📌Bean의 Life Cycle
Bean Life cycle 이란 객체가 언제 어떻게 생성되어 소멸되기 전까지 어떤 작업을 수행하고 언제, 어떻게 소멸되는지 일련의 과정을 이르는 말이다.
- Bean의 생명주기는 스프링 컨테이너에 의해 관리된다.
- Spring의 Bean은 Java 또는 XML bean 정의를 기반으로 IoC 컨테이너가 시작될 때 인스턴스화 되어야 한다.
- 빈의 초기화와 소멸 전 실행되길 원하는 코드가 있다면 init(), destroy() 메서드에 사용자 정의가 가능하다.
Spring Bean Life Cycle 프로세스
- 스프링 컨테이너 시작
- 스프링 빈 인스턴스 생성
- 의존성 주입
- 초기화 콜백 : 빈이 생성되고, 빈의 의존관계 주입이 완료된 후 호출
- 사용
- 소멸전 콜백 :빈이 소멸되기 직전에 호출
- 스프링 종료
- Spring 빈 생명주기 콜백 구현 방법
1) InitializingBean, DisposableBean callback interfaces 구현
- afterPropertiesSet() 및 destroy() 메소드 재정의
2) 설정 정보에 초기화 메서드 init( ), 종료 메서드 destory( ) 지정
3) @PostConstruct, @PreDestroy 애노테이션 사용
1. InitializingBean, DisposableBean Interfaces
- InitializingBean
- afterPropertiesSet() : 컨테이너가 시작되고 빈이 인스턴스화 됐을때 실행되는 메서드
- DisposableBean
- destroy() : 컨테이너가 닫힌 직후에 실행되는 메서드
- destroy 메서드를 호출하려면 ConfigurableApplicationContext의 close() 메소드 를 호출해야한다.
package beans; import org.springframework.beans.factory.DisposableBean; import org.springframework.beans.factory.InitializingBean; public class HelloWorld implements InitializingBean,DisposableBean { @Override // It is the init() method // of our bean and it gets // invoked on bean instantiation public void afterPropertiesSet() throws Exception { System.out.println( "Bean HelloWorld has been " + "instantiated and I'm the " + "init() method"); } @Override // This method is invoked // just after the container // is closed public void destroy() throws Exception { System.out.println( "Container has been closed " + "and I'm the destroy() method"); } }
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN 2.0//EN" "http://www.springframework.org/dtd/spring-beans-2.0.dtd"> <beans> <bean id="hw" class="beans.HelloWorld"/> </beans>
// Java program to call the // bean initialized above import org.springframework.context.ConfigurableApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; import beans.HelloWorld; // Driver class public class Client { public static void main(String[] args) throws Exception { // Loading the Spring XML configuration // file into the spring container and // it will create the instance of the bean // as it loads into container ConfigurableApplicationContext cap = new ClassPathXmlApplicationContext( "resources/spring.xml"); // It will close the spring container // and as a result invokes the // destroy() method cap.close(); } }
단점
- 해당 인터페이스는 스프링 전용 인터페이스로 해당 코드가 인터페이스에 의존한다.
- 인터페이스를 구현하기 때문에 메서드명을 변경할 수 없다.
- 코드를 고칠 수 없는 외부 라이브러리에 적용 불가능하다.
→ 스프링 초창기에 나온 방법으로 지금은 거의 사용하지 않는다고 한다.
2. 설정 정보에 사용자 정의 init() 및 destroy() 메서드 등록
설정파일에 init-method, destroy-method 속성을 사용하여 초기화, 소멸 메서드를 각각 등록하여 정의할 수 있다.
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN 2.0//EN" "http://www.springframework.org/dtd/spring-beans-2.0.dtd"> <beans> <bean id="hw" class="beans.HelloWorld" init-method="init" destroy-method="destroy"/> </beans>
// Java program to create a bean // in the spring framework package beans; public class HelloWorld { // This method executes // automatically as the bean // is instantiated public void init() throws Exception { System.out.println( "Bean HelloWorld has been " + "instantiated and I'm " + "the init() method"); } // This method executes // when the spring container // is closed public void destroy() throws Exception { System.out.println( "Container has been closed " + "and I'm the destroy() method"); } }
- 수정할 수 없는 외부 클래스, InitializingBean과 DisposableBean 두 인터페이스를 구현시킬 수 없는 클래스의 객체 스프링 컨테이너에 등록할 때 유용하다.
- 메서드 명을 자유롭게 부여할 수있고, 스프링 코드에 의존하지 않는다.
- 설정 정보를 사용하기 때문에 코드를 고칠 수 없는 외부 라이브러리에도 초기화, 종료 메서드를 적용할 수 있다.
3. @PostConstruct, @PreDestroy Annotation
- @PostConstruct : 컨테이너가 시작되고 빈이 인스턴스화 됐을때 실행될 초기화 메서드에 작성
- @PreDestroy : 컨테이너가 닫힌 직후 실행될 소멸 메서드에 작성
package beans; import javax.annotation.PostConstruct; import javax.annotation.PreDestroy; public class HelloWorld { // Annotate this method to execute it // automatically as the bean is // instantiated @PostConstruct public void init() throws Exception { System.out.println( "Bean HelloWorld has been " + "instantiated and I'm the " + "init() method"); } // Annotate this method to execute it // when Spring container is closed @PreDestroy public void destroy() throws Exception { System.out.println( "Container has been closed " + "and I'm the destroy() method"); } }
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN 2.0//EN" "http://www.springframework.org/dtd/spring-beans-2.0.dtd"> <beans> <!-- activate the @PostConstruct and @PreDestroy annotation --> <bean class="org.springframework.context.annotation.CommonAnnotationBeanPostProcessor"/> <!-- configure the bean --> <bean class="beans.HelloWorld"/> </beans>
- 최신 스프링에서 가장 권장하는 방법
- 애노테이션 하나만 붙이면 되므로 매우 편리하다.
- 스프링에 종속적인 기술이 아니라 자바 표준이므로 스프링이 아닌 다른 컨테이너에서도 동작한다.
- 단점은 외부 라이브러리에는 적용하지 못한다는 점이 있다.
참고포스팅
https://velog.io/@hosunghan0821/Spring-Spring-bean-life-cycle
https://www.geeksforgeeks.org/bean-life-cycle-in-java-spring/
https://dodokwon.tistory.com/57
📌Bean Scope
스프링은 Bean이라는 개념으로 자바객체를 만들고 싱글톤화 시켜 관리한다.
이 객체들은 스프링 컨테이너의 의해 생성되고 소멸되는 등의 관리가 이루어지는데,
이때 bean이 관리되는 범위를 Bean scope라고 한다.
- Spring Scope 종류
1) singleton
- 스프링 기본 Scope, 스프링 컨테이너의 시작과 종료까지 유지되는 가장 넓은 범위의 스코프
- 하나의 컨테이너 안에서 단 하나의 객체만 존재
- 애플리케이션 구동시 스프링이 bean마다 하나의 객체를 생성하는 것을 의미
- 처음 생성된 Bean을 별도의 캐시에 저장하여 해당 Bean에 대한 다음 요청부터는 캐시에 있는 Bean을 제공
- @Component, @Configuration + @bean의 조합으로 등록된 bean들의 기본 scope
2) prototype
- 빈에 대한 요청이 있을 때 마다 새로운 Bean을 만들어냄
- 스프링에서 새로운 Bean의 생성, 의존성 주입까지만 관여 후 더이상 관리하지 않는 매우 짧은 범위의 스코프
- Bean의 소멸에 대한 콜백이 설정되어있더라도 더이상 스프링에서 관리하지 않기 때문에 호출되지않음, 따라서 객체 자원 반환에 신경 써줘야함
여기부터 웹에서만 동작하는 Scope
3) request
- HTTP 요청 하나 당 하나의 Bean을 만듦
- 어떤 요청 안에서 빈의 상태가 변경되어도 다른 요청에 영향이 가지 않음
- 웹 요청이 들어오고 나갈 때까지 유지되는 스코프
4) session
- HTTP 세션 한 번에 하나의 Bean을 만듦
- 웹 세션이 생성되고 종료될 때까지 유지되는 스코프
5) application
- ServletContext와 동일한 생명주기를 가지는 Bean을 만듦
- 해당 Scope를 가진 빈은 ServletContext의 속성으로 직접 등록됨
- 웹의 서블릿 컨텍스트와 같은 범위로 유지되는 스코프
6) websocket
- websocket과 동일한 생명주기를 가지는 Bean을 만듦
참고 포스팅
https://velog.io/@bjk1649/8cq6c4da https://velog.io/@may_yun/Spring-Bean-Scope와-종류
📌Bean Profiles
스프링 프레임워크에서는 설정 파일을 특정 환경이나 목적에 맞게 선택적으로 사용할 수 있도록 그룹화할 수 있으며, 이 기능을 프로파일(profile)이라고 한다. 사용자의 설정으로 활성화시킨 Profile의 해당 bean이 Runtime시에 동작하도록 하는 기능이다. 보통 개발시점과 운영시점에 bean의 Profile설정 변경만으로 Spring Container에서 Bean적용이 달리 적용되도록 하는데 쓰인다.
- Bean Profile 설정 방법
1) XML Profile 설정
- <beans> 요소의 profile 속성을 활용
2) Annotation 설정
- @Profile 애너테이션 사용
- XML Profile 설정
1. XML 파일 하나에 하나의 프로파일
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd" profile="development"> <!-- 이 안에서 정의한 내용은 지정한 프로파일 내에서만 유효하다. --> </beans>
2. XML 파일 하나에 여러 개의 프로파일
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> <beans profile="development"> <!-- 이 안에서 정의한 내용은 development 프로파일 내에서만 유효하다. --> <bean id="dataSource" class="..."> <!-- 생략 --> </bean> </beans> <beans profile="staging"> <!-- 이 안에서 정의한 내용은 staging 프로파일 내에서만 유효하다. --> <bean id="dataSource" class="..."> <!-- 생략 --> </bean> </beans> <beans profile="production"> <!-- 이 안에서 정의한 내용은 production 프로파일 내에서만 유효하다. --> <bean id="dataSource" class="..."> <!-- 생략 --> </bean> </beans> </beans>
- Annotiation Profile 설정
@Component @Profile("staging") public class DummyUserRepository implements UserRepository { // 생략 }
- Profile 선택 방법
: 프로그램 실행 시 어떤 프로파일을 선택해야 할지 알려줌. spring.profiles.active라는 프로퍼티 값과 사용할 프로파일 이름을 지정하면 된다.
- 자바 명령행 옵션으로 프로파일을 지정하는 방법
-Dspring.profiles.active=production
프로파일을 여러 개 선택하고 싶으면 쉼표로 구분해서 나열가능.
- 환경 변수로 프로파일을 지정하는 방법
export SPRING_PROFILES_ACTIVE=production
- web.xml에 프로파일을 지정하는 방법
<context-param> <param-name>spring.profiles.active</param-name> <param-value>production</param-value> </context-param>
spring.profiles.active를 따로 지정하지 않았다면 기본값으로 spring.profiles.default에서 지정된 프로파일을 사용한다. 웹 애플리케이션이라면 위와 같이 web.xml에 spring.profiles.default를 설정해서 기본 프로파일을 지정한 다음 프로파일을 바꾸고 싶을 때만 자바 명령행 옵션으로 spring.profiles.active를 지정해 기본 프로파일을 덮어쓰면 된다.
- XML로 Profile설정한 경우 Java 코드로 프로파일 지정하는 방법
GenericXmlApplicationContext ctx = new GenericXmlApplicationContext(); ctx.getEnvironment().setActiveProfiles("production"); ctx.load("classpath:/com/bank/config/xml/*-config.xml"); ctx.refresh();
- 애너테이션으로 Profile설정한 경우 Java 코드로 프로파일 지정하는 방법
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(); ctx.getEnvironment().setActiveProfiles("dev"); ctx.scan("com.bank.config.code"); // find and register all @Configuration classes within ctx.refresh();
참고 포스팅
📌Bean ApplicationContext
ApplicationContext는 스프링 프레임워크의 가장 대표적인 객체로 BeanFactory를 상속받아서 구현된 객체이다. BeanFactory만 상속받는 것이 아니라, 다른 여러 스프링 인터페이스들을 상속받아서 구현되어 있어 Bean을 조회하고 관리하는 기능뿐만 아니라, 확장 기능을 제공한다.
- BeanFactory : Bean(객체)를 생성, 연결 등의 기본 기능을 정의 (Parent)
- ApplicationContext : BeanFactory를 확장해서 여러 기능을 추가 정의 (Child)
- Bean 요청 시 처리 과정
- ApplicationContext는 @Configuration이 붙은 클래스들을 설정 정보로 등록해두고, @Bean이 붙은 메소드의 이름으로 빈 목록을 생성한다.
- 클라이언트가 해당 빈을 요청한다.
- ApplicationContext는 자신의 빈 목록에서 요청한 이름이 있는지 찾는다.
- ApplicationContext는 설정 클래스로부터 빈 생성을 요청하고, 생성된 빈을 돌려준다.
참고 포스팅
https://velog.io/@gwon477/Spring-Bean과-ApplicationContext https://mangkyu.tistory.com/151
https://belklog.tistory.com/entry/Spring-FrameworkSpring-Bean과-Application-Context
https://zigo-autumn.tistory.com/m/entry/AOP-심화-feat-Life-Cycle-of-Bean-Advice-예제
'DEV > Spring' 카테고리의 다른 글
[Spring] AOP 심화 - JoinPoint와 ProceedingJoinPoint / 동작 원리 / 프록시 / JDK Proxy와 CGLib Proxy (0) 2024.05.17 [Spring] 스프링 프레임워크 특징/ POJO / IoC / DI / AOP / PSA (0) 2024.05.08 [Spring] Jasypt 프로퍼티스 암호화 (0) 2022.09.20 전자정부프레임워크기반 게시판 만들기 (6) 파일 업로드,다운로드 (2) 2020.12.31 전자정부프레임워크기반 게시판 만들기 (5) 페이징,검색 (2) 2020.12.30