스프링 IoC [Inversion of Control]

728x90

7강. [IoC 컨테이너]

-IoC(Inversion of Control); 제어 역전
-프레임워크가 객체 제어권을 가지는 것 의미(원래는 개발자가 객체 제어권 가졌음)
-개발자가 객체 생성 등 관련 코드를 설정 파일에 작성하면
이를 토대로 프레임워크가 해당 객체를 생성,반환하고 동작 순서를 결정하는 등. 객체 제어를 직접 수행함

[IoC 컨테이너 종류]

BeanFactory(예전 버전)
: 클래스를 통해 객체를 생성하고 전달함
: 상속 등 객체 간의 관계를 형성/관리함
: Bean에 관련된 설정을 위한 xml 파일은 즉시 로딩.
        객체는 개발자가 요구할 때 생성.
  ex) XmlBeanFactory




ApplicationContext(현재 버전)
: 클래스를 통해 객체를 생성하고 전달함
: 상속 등 객체 간의 관계를 형성/관리함
: 국제화 지원 등(문자열 관련 다양한 기능 제공)
: 리스너로 등록된 Bean에 이벤트 발생시킬 수 있음
: Bean에 관련된 설정을 위한 xml 파일은 즉시 로딩
       + 객체를 미리 생성하여 가지고 있음.
  ex) ClassPathXmlApplicationContext 
    FileSystemXmlApplicationContext

    XmlWebApplicationContext

[POJO Class] = [Bean 객체]

-POJO(Plain Old Java Object) : 홀로 독립적. 단순 기능만을 가진 객체 의미


[TestBean 객체]

public class TestBean {

	//생성자 
	public TestBean() {
		System.out.println("TestBean의 생성자");
	}
}

[bean.xml 파일에 id 속성 정의]

<?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 정의 -->
<bean id = 't2' class= 'kr.co.softcampus.beans.TestBean'/>
	

</beans>

[MainClass.java]

public class MainClass {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		//test1();
		//test2();
		//test3();
		test4();
	}
	//BeanFactory -패키지 내부 
	public static void test1() {
		//패키지 내부의 xml 파일 가져올 때 사용 
		ClassPathResource res = new ClassPathResource("kr/co/softcampus/config/beans.xml");
		XmlBeanFactory factory = new XmlBeanFactory(res);

		TestBean t2 = factory.getBean("t1", TestBean.class);
		System.out.printf("t2: %s\n", t2);
		
	}
	//BeanFactory - 패키지 외부
	public static void test2() {
		//패키지 외부의 xml 파일 가져올 때 사용 
		FileSystemResource rs = new FileSystemResource("beans.xml");
		XmlBeanFactory factory = new XmlBeanFactory(rs);
		
		TestBean t1 = factory.getBean("t2", TestBean.class);
		System.out.printf("t1 : %s\n", t1);
	}
	
	//ApplicationContext - 패키지 내부 
	public static void test3() {
		//패키지 내부의 xml 파일 가져올 때 사용 
		ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext("kr/co/softcampus/config/beans.xml");
		TestBean t1 = ctx.getBean("t1", TestBean.class);
		System.out.printf("t1: %s\n", t1);
		
		ctx.close();
	}
	//ApplicationContext - 패키지 외부
	public static void test4() {
		//패키지 외부의 xml 파일 가져올 때 사용 
		FileSystemXmlApplicationContext ctx = new FileSystemXmlApplicationContext("beans.xml");
		
		TestBean t1 = ctx.getBean("t2", TestBean.class);
		System.out.printf("t1: %s\n", t1);
		
		TestBean t2 = ctx.getBean("t2", TestBean.class);
		System.out.printf("t2: %s\n", t2);
		ctx.close();
	}
	
}

[BeanFactory(예전 버전) - IoC 컨테이너의 한 종류]

<beans.xml 파일 위치에 따른 차이>

(1) 패키지 내부에 위치  (2) 패키지 외부에 위치
ClassPathResource 사용 FileSystemResource 사용

 

[ApplicationContext(현재 버전) - IoC 컨테이너의 한 종류]

<beans.xml 파일 위치에 따른 차이>

(1) 패키지 내부에 위치  (2) 패키지 외부에 위치
ClassPathXmlApplicationContext 사용  FileSystemXmlApplicationContext 사용

 

<정리>

-스프링 프레임워크는 IoC 컨테이너를 이용해 Bean 객체들을 관리함


8강. [Spring Bean 객체 생성]

-Spring에서는 사용할 Bean 객체를 bean configuration file에 정의해두고,

필요할 때 객체를 가져와 사용하는 방법을 이용한다

[bean 태그 기본 속성]

class   : 객체 생성하기 위해 사용할 클래스 지정
id       : Bean 객체 가져올 때 사용할 이름 지정
lazy-init : 싱글톤인 경우, xml 로딩할 때 객체 생성여부 설정
           -> true 설정 : xml 로딩 시 객체를 생성하지 않고, 객체를 가져올 때 생성
scope: 객체의 범위 설정
           ->singleton : 객체 한 종류만 생성해서 사용함
           ->prototype : 객체를 가져올 때마다 새로운 객체를 생성함

[beans.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">

	<!-- xml 로딩 시 자동으로 객체 생성됨 -->
	<!-- 현재까지의 진도상 id 속성 따로 없다면 객체의 주소값을 받아서 사용할 수 X -->
	<bean class='kr.co.softcampus.beans.TestBean' />

	<!-- xml 로딩할 때 자동으로 객체가 생성됨 -->
	<!-- id 속성에 이름을 부여하면 getBean 메소드를 통해 객체의 주소값을 받아서 사용할 수 O -->
	<bean id='test1' class='kr.co.softcampus.beans.TestBean' />

	<!-- lazy-init에 true 넣어주면 xml 로딩할 때 객체 생성 X -->
	<!-- getBean 메소드를 호출할 떄 객체가 생성되며 싱글톤이기 때문에 한 종류의 객체만 생성됨 -->
	<bean id='test2' class='kr.co.softcampus.beans.TestBean'
		lazy-init="true" />
	<!-- scope 에 prototype 넣어주면 xml 로딩 시 객체 생성 X -->
	<!-- getBean 메소드 호출할 때마다 새로운 객체 생성해서 반환함 -->
	<bean id='test3' class='kr.co.softcampus.beans.TestBean'
		scope='prototype' />
</beans>

[MainClass.java]

public class MainClass {
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		//패키지 내부에 xml파일 존재하므로
		ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext("kr/co/softcampus/config/beans.xml");
		
		//id= test1 인 bean 객체 주소값을 받아옴
		TestBean t1= ctx.getBean("test1", TestBean.class);
		System.out.printf("t1: %s\n", t1);
		
		TestBean t2 = ctx.getBean("test1", TestBean.class);
		System.out.printf("t2: %s\n", t2);
		
		//id= test2 인 bean 객체 주소값을 받아옴
		TestBean t3 = ctx.getBean("test2", TestBean.class);
		System.out.printf("t3: %s\n", t3);
	
		//id = test3 인 bean 객체 주소값을 받아옴
		TestBean t5 = ctx.getBean("test3", TestBean.class);
		System.out.printf("t5: %s\n", t5);
		
		TestBean t6 = ctx.getBean("test3", TestBean.class);
		System.out.printf("t6: %s\n", t6);
		
		ctx.close();
	}
}

- spring에서는 프로그램에서 사용할 객체를 bean configuration 파일에 정의하여 사용함


9강. [Bean 객체의 생명주기]

[Bean 객체 생성 시기]

<singleton인 경우> xml파일 로딩 시 객체 생성됨
<singleton이면서 lazy-init 속성이 true인 경우> getBean() 메소드 사용 시 객체 생성됨
<prothtype인 경우> getBean() 메소드 사용 시 객체 생성됨

[Bean 객체 소멸 시기]

<IoC 컨테이너 종료 시>   객체 소멸됨


[객체 생성과 소멸 시 호출될 메소드 등록]

-객체 생성되면 가장 먼저 생성자가 호출됨

init-method 생성자 호출 이후 자동으로 호출됨
destroy-method 객체 소멸 시 자동으로 호출됨
default-init-method  init-method를 설정하지 않은 경우
자동으로 호출됨
default-destroy-method destroy-method를 설정하지 않은 경우 자동으로 호출됨

[명시적으로 지정한 메소드 없을 경우]

default-init-method 아무 일도 발생 X
default-destroy-method 아무 일도 발생 X
init-method 오류 발생 O
destroy-method 오류 발생 O

-spring에서는 객체가 생성될 때 호출될 메소드와 소멸될 때 호출될 메소드를 지정 가능O


10강. [BeanPostProcessor]

[BeanPostProcessor]

-Bean 객체를 정의할 때 init-method 속성 설정하면
                                             객체 생성 시 자동으로 호출될 메소드 지정 O

-   단)  이 때 동시에 BeanPostProcessor 인터페이스 구현 클래스 정의하면
                           -> Bean 객체 생성 시 호출될 init 메소드 호출 전/후에 다른 메소드 호출도 가능 O

<BeanPostProcessor 인터페이스 내부 메소드>

     1) postProcessBeforeInitialization 메소드
                           : init-method 지정된 메소드 호출 전 호출됨

     2) postProcessAfterInitialization 메소드 
                           : init-method 지정된 메소드 호출 후 호출됨

                 // 이 두 메소드는 init-method 지정되어 있지 않아도 자동 호출
  <정리>
Spring에서는 객체가 생성될 때
 init-method로 지정된 메소드 호출되기 전/후에 다른 메소드 호출할 수 있는 BeanPostProcessor 인터페이스를 지원한다.

 이 인터페이스를 구현한 객체에서 메소드 재정의한 뒤,
beans.xml파일에서 빈으로 등록할 경우, 자동으로 init 메소드 호출 전/후에 맞춰 재정의한 메소드가 호출된다.

kr.co.softcampus.config,[beans.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">

<!-- Bean 등록  -->
 <bean id = 't1' class = 'kr.co.softcampus.beans.TestBean1' lazy-init='true' init-method="bean1_init"/>
 <bean id = 't2' class = 'kr.co.softcampus.beans.TestBean2' lazy-init='true' init-method="bean2_init"/>

<!-- 우리가 직접 프로젝트 안에서 getBean하여 사용할 용도는 아니므로 그냥 id 없이 등록만 해줌. 나머지 처리는 스프링이 해줌 --> 
 <bean class='kr.co.softcampus.processor.TestBeanPostProcessor'/>

</beans>

kr.co.softcampus.processor.[TestBeanPostProcessor.java]

public class TestBeanPostProcessor implements BeanPostProcessor{

	//init 메소드 호출 전에 호출되는 메소드 
	public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
	// TODO Auto-generated method stub
		System.out.println("Before");
		switch(beanName) { //인수로 들어온 bean이름을 기준으로 빈을 따로 처리 할 수도 있음 
		case "t1":
			System.out.println("id가 t1인 Bean 객체 생성");
			break;
		case "t2":
			System.out.println("id가 t2인 Bean 객체 생성");
			break;
		}
	return bean; //들어왔던 빈 객체 다시 반환해줌 
	}
	
	//init 메소드 호출 후에 호출되는 메소드
	public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
		// TODO Auto-generated method stub
		System.out.println("After");
		return bean; //들어왔던 빈 객체 다시 반환해줌 
	}
}

kr.co.softcampus.main.[MainClass.java]

public class MainClass {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
ClassPathXmlApplicationContext ctx 
          = new ClassPathXmlApplicationContext ("kr/co/softcampus/config/beans.xml");
		
		TestBean1 t1 = ctx.getBean("t1", TestBean1.class );
		System.out.printf("t1", t1);
		
		TestBean2 t2 = ctx.getBean("t2", TestBean2.class);
		System.out.printf("t2", t2);
		
		ctx.close();
		
	}

}
[참고] - SpringFramework 개발자를 위한 실습을 통한 입문 과정
728x90