-
실습 코드 repo : 저장소
-
- 스프링 컨테이너 생성
GenericXmlApplicationContext ctx = new GenericXmlApplicationContext(); 또는 GenericXmlApplicationContext ctx = new GenericXmlApplicationContext("classpath:applicationCTX.xml");
-
- 스프링 컨테이너 설정
- 스프링 컨테이너를 생성할 때, 생성자를 통해 생성했다면 refresh() 메소드를 호출 해 줄 필요가 없지만,
- ctx의 load() 메소드를 통해서 생성했을 경우, refresh() 메소드를 꼭 호출 해야 한다.
ctx.load("classpath:applicationCTX.xml"); ctx.refresh();
-
- 스프링 컨테이너 사용
Student student = ctx.getBean("student", Student.class); System.out.println("이름: " + student.getName()); System.out.println("나이: " + student.getAge());
-
- 스프링 컨테이너 종료
ctx.close();
-
실습 코드 repo : 저장소
-
이번에는 스프링 빈의 생명 주기를 알아본다.
-
빈 초기화 과정과 빈 소멸 과정에서 호출되는 메소드를 알아본다.
public class MainClass {
public static void main(String[] args) {
GenericXmlApplicationContext ctx = new GenericXmlApplicationContext();
ctx.load("classpath:applicationCTX.xml");
ctx.refresh();
ctx.close();
}
}
-
위의 메인 클래스에서
ctx.refresh()
메소드가 호출되면서 빈 이 초기화 될 때, 아래의afterPropertiesSet()
메소드가 호출된다. -
초기화 과정중 해야 할 작업이 있다면, 이 메소드에서 하면 된다.
@Override public void afterPropertiesSet() throws Exception { ... }
-
메인 클래스에서
cts.close()
메소드가 호출되면서 빈이 소멸 될때, 아래의destroy()
메소드가 호출된다. 마찬가지로 빈이 소멸하는 과정중에서 해야 할 작업이 있다면, 이 메소드에서 해주면 된다.@Override public void destroy() throws Exception { ... }
ctx.close() 의 경우 컨테이너가 소멸 하는 단계이다. 컨테이너가 소멸 하면, 빈은 자동 소멸 된다. 빈만 소멸하게 해야 하는 경우 student.destroy() API를 이용하면 된다.
- InitializingBean, DisposableBean을 구현상속 한 Student 클래스
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.InitializingBean;
public class Student implements InitializingBean, DisposableBean {
private String name;
private int age;
public Student(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public int getAge() {
return age;
}
@Override
public void destroy() throws Exception {
System.out.println("destory()");
}
@Override
public void afterPropertiesSet() throws Exception {
System.out.println("afterPropertiesSet()");
}
}
-
위에서는 구현상속을 통해서 메소드를 Override하는 방식이었고, 어노테이션을 사용하는 방법도 있다.
-
위의 메인 클래스에서
ctx.refresh()
메소드가 호출되면서 빈 이 초기화 될 때, 아래의@PostConstruct
어노테이션이 선언된 메소드가 호출 된다. 메소드 명은 자유롭게 정의할 수 있다.@PostConstruct public void initMethod() { System.out.println("initMethod()"); }
-
위의 메인 클래스에서
ctx.close()
메소드가 호출되면서 빈이 소멸 될 때, 아래의@preDestroy
어노테이션이 선언된 메소드가 호출 된다. 마찬가지로 메소드 명은 자유롭게 정의할 수 있다.@preDestroy public void destroyMethod() { System.out.println("destroyMethod()"); }
-
@PostConstruct, @PreDestroy 어노테이션이 정의 된 OtherStudent 클래스
import javax.annotation.*;
public class OtherStudent {
private String name;
private int age;
public OtherStudent(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public int getAge() {
return age;
}
@PostConstruct
public void initMethod() {
System.out.println("initMethod()");
}
@PreDestroy
public void destroyMethod() {
System.out.println("destroyMethod()");
}
}
-
실습 코드 repo : 저장소
-
스프링 컨테이너가 생성되고, 스프링 빈이 생성 될 때, 생성된 스프링 빈은 scope를 가지고 있다.
-
scope랑 쉽게 생각해서 해당하는 객체가 어디까지 영향을 미치는지 결정하는 것이라고 생각하면 된다.
-
applicationCTX.xml
- 아래의 xml에서 bean의 scope가 singleton으로 지정되어 있다. singleton객체는 단 하나만 생성될 수 있는 객체이다. bean의 scope default값은 singleton이다
<?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">
<bean id="student" class="com.javalec.ex.Student" scope="singleton">
<constructor-arg value="홍길동"></constructor-arg>
<constructor-arg value="26"></constructor-arg>
</bean>
</beans>
- MainClass.java
- 아래의 메인 클래스에서 보면 applicationCTX.xml 즉, 스프링 config 파일을 통해서 스프링 컨테이너를 생성하고, getBean() 메소드를 통해서 Student 빈을 가져다 쓴다.
- student2에 빈을 할당할 때도 보면, 새로이 객체를 생성하는 것이 아니라 이미 생성된 객체를 스프링 컨테이너에서 가져와서 setter로 값을 변경해서 사용하고 있다.
- 자바의 메모리 구조상으로 봤을 때, student1과 student2가 하나의 Student객체를 바라보고 있는 형태가 될 것이다.
- 맨 아래에서 두 객체가 같은 객체인 것을 직접 확인 해 볼 수 있다.
public class MainClass {
public static void main(String[] args) {
AbstractApplicationContext ctx = new GenericXmlApplicationContext("classpath:applicationCTX.xml");
Student student1 = ctx.getBean("student", Student.class);
System.out.println("이름: " + student1.getName());
System.out.println("나이: " + student1.getAge());
Student student2 = ctx.getBean("student", Student.class);
student2.setName("홍길순");
student2.setAge(23);
System.out.println("이름: " + student2.getName());
System.out.println("나이: " + student2.getAge());
if (student1.equals(student2))
System.out.println("student1 == student2");
else
System.out.println("student1 != student2");
ctx.close();
}
}
이름: 홍길동
나이: 26
이름: 홍길순
나이: 23
student1 == student2
- Student.java
public class Student {
private String name;
private int age;
public Student(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public int getAge() {
return age;
}
public void setName(String name) {
this.name = name;
}
public void setAge(int age) {
this.age = age;
}
}