IoC(Inversion Of Control) : 제어의 역행
- IoC의 개념을 적용함으로 인해 얻을 수 있는 장점 : Container 기능을 제공하여 객체간의 결합도 감소
* 개발자가 객체를 만드는 대신 또 다른 무엇인가(Container)가 만든 객체를 제공받아 사용하면 결함도를 떨어뜨릴 수 있게 하는 것
1. 객체 결합과 유지 보수성
1) 결합도 : 소프트웨어 코드의 한 요소가 다른 것과 얼마나 강력하게 연결되어 있는지를 나타냄
→ 한 객체 안에서 다른 객체의 메소드를 호출하거나 멤버 변수에 접근할 때 두 객체가 연결되어 있다라고 표현
2) 클래스의 결합과 유지보수성의 관계
- 클래스가 결합되어 있다는 건 결합되어 이용하고 있는 클래스가 유지보수될 때 클래스와 결합되어 있는 다른 클래스도 같이 요쥬보수되어야 할 가능성이 아주 높다는 것
- 클래스의 결합이 심하면 심할수록 유지보수성이 감소
3) 결함도 감소
- 다형성(Interface - 오버라이딩)
- Container(Factory Class) 이용
2. Container : 객체의 생성, 운용, 소멸 등의 객체의 라이프사이클 관리는 담당
1) 주요 기능
① Lifecycle Management
② Configuration
③ Lookup
④ Dependency Resolution
2) 필요성
- 컴포넌트/오브젝트의 자유로운 삽입이 가능하도록 하기 위한 Calling Code의 독립성을 위함
- 서비스의 lookup이나 configuration이 일관성을 갖도록 하기 위함
- 단일화된 서비스의 접근방법을 제공하기 위함
⭐Spring Container⭐
: 환경설정파일(Spring Bean Configuration File - XML)로부터 클래스를 제공받아 객체를 생성하여 관리
< 수업 순서 - 2024.08.21 >
xyz.itwill03.spring
1. MassageObject : 인터페이스 - for 결합도 감소

2. HelloMessageObject : MassageObject 인터페이스를 상속받아 메소드 오버라이드, "Hello!!!" 메세지 반환(return)

3. MessagePrintObjcet : MessageObjcet 인터페이스를 상속받은 자식클래스의 객체를 저장하기 위한 필드 작성 - 필드에 객체를 저장하기 위해 생성자 또는 Setter 메소드 작성(의존관계)
- 객체가 null이면 NullPointerException 발생

4. MessagePrintApp : 프로그램 - 메세지 프린트 실행 클래스 / ApplicationContext 객체 생성

5. HiMassageObject : 출력 내용 변경을 위한 클래스

📍기존 new 연산자로 객체를 생성하면 출력 내용을 변경하기 위해 "Hi!!!" 메세지를 반환하는 객체를 가진 클래스로 연관되어 있는 클래스를 전부 변경해줘야하는 불편함이 있음 → 해결법 : spring container 이용, 프로그램을 수정하지 않고 XML만 변경하여 관계 수정 가능(setter 메소드 호출 필요 X, 객체 간의 관계를 맺을 필요 X)


6. 03_message.xml : xml 파일 생성 - 환경설정파일(Spring Bean Configuration File)
- src/main/resources 폴더 : 환경설정파일 저장 - ex) xml파일 등
- 스키마 파일 선택 - beans 엘리먼트(기본 Name Spaces) 사용
- 스키마 파일이 제공해주는 엘리먼트를 쉽게 제공받아 환경설정파일 생성 가능

- Spring Bean : 스프링 컨테이너에 의해 관리(생성, 제공, 소멸)되는 객체(클래스)
→ 스프링 컨테이너는 클래스를 문자열로 제공받아 리플렉션(Reflection) 기술을 사용해 객체 생성
- bean 엘리먼트 : 스프링 컨테이너에게 클래스를 제공하여 Spring Bean으로 사용되도록 설정하는 엘리먼트 / 하위 엘리먼트를 사용하여 Spring Bean에 대한 의존관계 설정
- class 속성 : 스프링 컨테이너에 의해 관리될 클래스를 속성값으로 설정(필수)
- id 속성 : Spring Bean을 구분하기 위한 식별자를 속성값으로 설정(클래스의 이름을 이용하여 작성하는 것을 권장)
- property 엘리먼트(하위) : name 속성에 객체를 저장하는 필드명을 속성값으로 설정, ref 속성에 Spring Bean id를 속성값으로 설정하여 객체 간 의존관계를 형성하는 엘리먼트
- MessagePrintObject 클래스와 HiMessageObject 클래스가 의존 관계를 이룸
📍property 속성의 ref 값을 hiMessageObject로 변경하면 완료
< BeanFactory 와 ApplicationContext 객체 >
→ 스프링 컨테이너로 사용할 수 있는 객체

* BeanFactory : BeanFactory 객체를 생성할 때 환경설정파일을 제공받아 BeanFactory 객체 초기화 처리
→ BeanFactory 객체는 환경설정파일에 등록된 클래스로 미리 객체를 생성하지 않고 객체 제공을 요청할 경우에 객체를 생성하여 제공
→ 환경설정파일을 읽어 객체를 Spring Bean으로 등록할 때 객체를 생성하지 않고 getBean() 메소드를 호출해 객체를 반환받을 때 객체 생성(요청할 때 생성)
⭐ ApplicationContext : ApplicationContext 객체를 생성할 때 환경설정파일을 제공받아 ApplicationContext 객체 초기화 처리
→ ApplicationContext 객체는 환경설정파일에 등록된 클래스로 미리 객체 생성
※ 초기화라는 것은 새로운 환경을 만들기 위한 준비를 한다라는 의미로 환경설정파일을 읽어드린 것을 초기화됐다고 함.
xyz.itwill04.bean
7. CreateBean : 기본 생성자와 display() 메소드 작성
8. CreateBeanApp : main 메소드로 출력
9. 04-1_beanCreate.xml : 스프링 컨테이너(Spring Bean(객체) 관리)


=> 설명 : BeanFactory 객체는 환경설정파일을 읽어드린 후 바로 객체를 생성하지 않고 객체를 사용하기 위해 제공을 요청한 경우에 객체를 생성하여 제공한다. 그에 반해 ApplicationContext 객체는 환경설정파일을 읽어드림과 동시에 미리 객체를 생성하여 만들어진 객체(스프링 컨테이너가 관리하는 객체)를 검색하여 사용
=> 설명 : 보통 ApplicationContext 객체를 이용하여 환경설정파일을 읽어드려 미리 객체를 생성한 뒤 사용하는 방법을 쓰지만 몇몇 경우 lazy-init 속성을 사용해 객체를 미리 생성하지 않고 사용할 때 생성하는 방법을 쓰는 경우도 있음.
< bean 속성 >
10. InitDestroyMethodBean : 스프링 컨테이너에 의해 관리될 클래스(Spring Bean)는 다양한 인터페이스를 상속받아 추상메소드 오버라이드 선언 가능

11. LazyInitBean : 기본 생성자 작성
12. FactoryMethodBean : 싱글톤 디자인 패턴을 적용하여 작성된 클래스(싱글톤 클래스)

13. DependsOnOneBean : 기본생성자 작성
14. DependsOnTwoBean : 기본생성자 작성
15. ScopeBean : 기본생성자 작성
16. 04-2_beanAttribute.xml : 환경설정파일
⭐bean 속성⭐
① init-method 속성 : 객체(Spring Bean)을 생성 후 초기화 처리하기 위해 자동 호출될 메소드의 이름을 속성값으로 설정
② destroy-method 속성 : 객체(Spring Bean)을 소멸 전 마무리 처리하기 위해 자동 호출될 메소드의 이름을 속성값으로 설정
③ lazy-init 속성 : false(기본값) 또는 true 중 하나를 속성값으로 설정(false : 스프링 컨테이너가 초기화될 때 객체를 미리 생성, true : 미리 생성하지 않고 getBean() 메소드를 호출할 때 객체 생성)
④ factory-method 속성 : 싱글톤 클래스에서 객체를 반환하는 메소드의 이름을 속성값으로 설정
→ 정적영역의 명령으로 객체를 생성하여 스프링 컨테이너에 의해 관리
=> 설명 : 환경설정파일에 싱글톤 클래스를 Spring Bean으로 등록하면 해당 클래스를 읽어 Class 객체로 생성한 후 정적영역의 명령으로 객체를 생성하고 스프링 컨테이너에 의해 객체를 다시 생성하여 객체 2개가 생성된다. factory-method 속성을 사용해 객체가 하나만 생성되도록 설정함.
⑤ depends-on 속성 : bean 엘리먼트의 식별자를 속성값으로 설정하여 bean 엘리먼트의 클래스로 객체를 생성하기 전에 depends-on 속성값으로 설정된 beanName의 클래스로 객체를 먼저 생성
⑥ scope 속성 : singleton(기본값), prototype, request, session 중 하나를 속성값으로 설정
- singleton 속성값 : 스프링 컨테이너가 bean 엘리먼트의 클래스로 객체를 하나만 생성하여 제공
- prototype 속성값 : 스프링 컨테이너가 bean 엘리먼트의 클래스로 객체를 여러개 생성하여 제공
17. BeanAttributeApp :


=> 설명 : ApplicationContext 객체를 이용해 환경설정파일을 읽어 드렸기 때문에 객체가 미리 만들어지고 InitDestroyMethodBean 클래스에 오버라이드된 메소드도 호출됨. 환경설정파일에 bean 엘리먼트의 init-method 속성으로 객체 생성 후 init() 메소드가 자동호출됨.
=> 설명 : FactoryMethedBean 클래스는 싱글톤 클래스로 아무 속성없이 bean 엘리먼트를 잘성한다면 정적영역 생성자와 스프링 컨테이너에 의해 객체가 2개 생성되지만 factory-method 속성값으로 인해 정적영역에서 생성된 객체를 스프링 컨테이너가 관리하는 것으로 객체가 1개만 생성됨
=> 설명 : depends-on 속성의 속성값이 dependOnTwoBean으로 설정되어 DependOnOneBean 클래스가 먼저 작성되어야 하는데 DependOnTwoBean 객체가 먼저 작성됨.
=> 설명 : LazyInitBean을 제외한 모든 객체가 미리 생성됨. 하지만 LazyInitBean 객체는 lazy-init 속성이 true이므로 객체를 사용할 때 생성됨.
=> 설명 : scope 속성값이 singleton인 경우 객체가 하나만 생성되어 제공되어 초기화 전(환경설정파일 다 읽기 전)에 객체 생성되고 객체가 하나만 생성되기 때문에 주소가 모두 동일.
=> 설명 : 하지만 prototype 인 경우 객체가 여러개 생성되고 lazy-init 속성값이 true로 자동으로 설정되어 초기화 후(환경설정파일 다 읽은 후)에 객체 생성되고 객체가 여러개 생성되기 때문에 주소가 모두 상이함.
=> 설명 : 객체 소면 전 마무리 처리하기 위해 destroy() 메소드가 자동 호출됨
18. AnnotationBean : 기본생성자, 메소드 작성
19. AnnotationBeanApp :


※ bean 등록하지 않고 스프링 컨테이너 생성 가능 → 어노테이션 사용
20. AnnotationConfigurationBean
- @Configuration : 스프링 컨테이너에 의해 관리될 객체를 생성하여 제공하는 기능을 클래스로 등록하기 위한 어노테이션 = Spring Bean Configuration File
- @Bean : 스프링 컨테이너에 의해 관리될 객체를 생성하여 반환하는 메소드를 등록하기 위한 어노테이션 = bean 엘리먼트
21. 04-3_beanAnnotation.xml : 환경설정파일

- component-scan : 스프링 컨테이너가 클래스에서 사용된 스프링 어노테이션을 검색해 처리할 수 있도록 설정하는 엘리먼트 → Configure Namespaces에서 context 추가해야 엘리먼트 사용 가능
- base-package 속성 : 스프링 어노테이션을 사용한 클래스가 작성된 패키지를 속성값으로 설정
=> 설명 : xyz.itwill04.bean 패키지에 있는 모든 클래스에 사용된 스프링 어노테이션을 검색해 처리
22. ComponentAnnotationBean
- @Component : 클래스를 스프링 컨테이너가 관리하는 Spring Bean으로 등록하기 위한 어노테이션
- value 속성 : 식별자 변경 가능

23. ComponentAnnotationBeanApp


=> 설명 : 부트에선 xml을 사용하지 않기 때문에 무조건 어노테이션을 이용. 어노테이션의 번거로움을 해결하기 위해 @Component(value="")을 이용. 기본생성자와 메소드가 작성된 클래스를 어노테이션을 이용해 Spring Bean으로 등록.
3. Spring 설정파일
1) Spring에서 XML 설정 파일이 가장 중요한 이유
- 간단하게 XML 설정 파일 수정만으로도 유지보수작업 가능
2) 여러개의 XML 파일 이용하여 설정하는 이유
- Spring 설정 파일에 모든 Bean들을 등록시키고 다양한 설정을 하면 XML 파일이 너무 길게 작성되어 관리 효율성 저하
3) Spring에서 Spring Bean 이용 방법
- XML 파일에 등록시켜 놓고 사용/ bean 엘리먼트 사용
//개발자가 new 연산자를 이용해서 객체를 생성하는 것이 아닌
제어의 역행 : 제어는 원래 객체를 가져다가 메소드를 호출한다거나 소멸시키는 일은 개발자가 명령을 통해 이루어지지만(new, [.] 연산자) 그런것들을 컨테이너라는 기능을 제공하는 객체를 이용해서 진행
factory 클래스를 기반으로 컨테이너 기능 사용
ioc기능을 이용해 객체를 관리.