회사에서 토비의 스프링 스터디를 시작하였다.
새로운 기분으로 정독하고 있으며, 정리한 내용을 학습목적으로 git에 올리고 있다.
이해가 가지 않는 내용도 있지만, 일단 1회독을 마치는 것을 목표로 진행하자!
https://github.com/cotgyu/toby_springstudy
1. 오브젝트와 의존관계
스프링 프레임워크에서 가장 중요한 것은 오브젝트(생성, 다른 오브젝트와의 관계, 사용, 소멸)이라 설명하면서, 스프링은 오브젝트를 어떻게 효과적으로 설계하고 구현, 사용 , 어떻게 개선해야하는 가의 기준을 마련해준다고 한다.
객체지향 기술, 설계, 구현, 검증된 프렉티스를 프레임워크로 제공
어떠한 변경이 일어날 때, 필요한 작업을 최소화하고 다른 곳에 영향이 가지 않게 하는 것이 중요한데, 이를 분리와 확장을 고려한 설계라 한다. 이 분리의 개념 중 하나인 관심사의 분리를 책에서 단계별 예제를 통해 소개하고 있다.
관심사의 분리 - 관심이 같은 것은 하나의 객체 안으로, 관심이 다른 것은 가능한 떨어뜨려 서로 영향이 가지 않게 분리
책에서는 간단한 사용자를 등록하는 UserDao를 제시하였는데, 여기에는 3가지 관심사가 있다.
- DB연결을 위한 커넥션
- SQL을 실행하는 statement
- statement, 커넥션 닫기
1장에서는 1번을 분리와 확장을 고려하여 개선하는 작업을 수행하였다.
첫번째로 이 커넥션 부분을 getConnention 이라는 함수로 빼내었고, 이를 통해 분리하였다. (메소드 추출 기법)
두번째로는 커넥션 확장을 위해 상속을 사용하였다. UserDao를 상속하고 서브클래스에서 추상메소드인 getConnention을 구현하여 DB커넥션 연결이라는 관심을 서브클래스로 분리하여 각자 원하는 구성의 getConnention을 사용하는 소개하고있다.
템플릿 메소드 패턴 - 슈퍼클래스의 기본적인 로직흐름을 만들고, 그 기능의 일부를 추상메소드나 오버라이딩이 가능한 메소드 등
으로 만든 뒤 서브클래스에서 필요에 맞게 구현, 사용하는 방법
팩토리 메소드 패턴 - 상속을 통해 기능을 확장하는 패턴으로 서브클래스에서 구체적인 오브젝트 생성방법을 결정한다.
하지만 이 상속을 이용한 방법도 슈퍼클래스 내부의 변경이 있을 때 모든 서브클래스를 함게 수정하거나 다시 개발할 수 있는 단점이 있음.(생각보다 밀접한 관계)
그래서 책에서는 세번째로 상속이 아닌 인터페이스를 통해 클래스를 분리하는 것을 소개한다. 이를 통해 UserDao는 인터페이스의 메소드를 통해 알 수 있는 기능에만 관심을 가지면 되지, 그 기능을 어떻게 구현했는지에는 관심을 둘 필요가 없어진다. (최종족으로 UserDao는 ConnentionMaker라는 인터페이스 외에는 어떤 클래스와 관계를 갖지 않게 개선하였다.)
책에서는 이 UserDao를 개선해온 결과를 객체지향 기술의 여러가지 이론을 통해 설명하였다.
개방 폐쇄 원칙(OCP) - 클래스나 모듈은 확장에는 열려 있어야하고 변경에는 닫혀있어야한다. (객체지향설계원칙)
높은 응집도 - 하나의 모듈이나 클래스가 하나의 책임 또는 관심사에 집중되어 있다.
낮은 응집도 - 하나의 오브젝트가 변경이 발생할 때, 관계를 맺고있는 다른 오브젝트에 변경을 최소화한다.
전략패턴 - 필요에 따라 변경이 필요한 알고리즘을 인터페이스를 통해 통째로 외부로 분리시키고, 이를 구현한 구체적인 알고리즘
클래스를 팔요에 따라 바꿔서 사용할 수 있게 하는 디자인 패턴
ex) DB연결방식(ConnentionMaker) - 알고리즘
스프링은 이러한 객체지향적 설계원칙과 디자인 패턴에 나타난 장점을 자연스럽게 개발자들이 활용할 수 있게 해주는 프레임워크라고 소개하고 있다.
책에서는 어떤 ConnectioNmaker를 사용할지 결정하는 기능을 UserDaoTest가 맡고 있는데, 이를 분리하면서 팩토리의 개념을 설명하고 있다.
(DaoFactory를 통해 UserDao타입의 오브젝트를 어떻게 만들고, 어떻게 준비하는지를 결정하도록 개선하였다.)
팩토리 - 객체의 생성방법을 결정하고 만들어진 오브젝트를 돌려줌.
이를 통해 책에서는 기존의 Dao는 모든 종류의 작업을 사용하는 쪽에서 제어하는 반면, 개선된 Dao는 ConnectionMaker의 구현 클래스 결정과 오브젝트의 생성의 제어권이 DaoFactory에 있음을 비교하며 IoC를 설명하고 있다.
IoC(제어의 역전) - 객체에 대한 제어권이 개발자로 부터 컨테이너에 넘어가면서 객체의 생성부터 생명주기 관리까지의
모든 것을 컨테이너가 맡아서 함
스프링은 IoC를 극적으로 적용하고 있는 프레임워크
스프링의 IoC
빈(bean): 스프링이 제어권을 가지고 직접 만들고 관계를 부여하는 오브젝트
(스프링 빈 - 스프링 컨테이너가 생성과 관계설정, 사용 등을 제어해주는 제어의 역전이 적용된 오브젝트)
빈 팩토리: 빈의 생성과 관계설정 같은 제어를 담당하는 IoC오브젝트
(어플리케이션 컨텍스트 - 별도의 정보를 참고해 빈의 생성, 관계 설정 등 제어작업 총괄)
어노테이션
@Configuration - 스프링이 오브젝트 설정을 담당하는 클래스로 인식
(어플리케이션 컨텍스트가 사용할 설정 정보)
@bean: 오브젝트 생성 담당
Application Context: 어플리케이션에서 IoC를 적용해서 관리할 모든 오브젝트에 대한 생성과 관계설정을 담당
- 오브젝트 팩토리가 아무리 많아도 이를 알아야하거나 직접 사용X
- 종합 IoC서비스를 제공한다.
- 빈을 검색하는 다양한 방법을 제공한다. (이름, 타입, 어노테이션)
책에서는 DaoFactory와 어플리케이션컨텍스트를 사용해서 UserDao를 호출 시 차이점을 보여주면서 싱글톤을 설명하고 있다.
DaoFactory를 직접 사용해서 UserDao를 여러번 호출 시 다른 오브젝트가 생성되지만, 애플리케이션 컨텍스트를 이용하면
동일한 오브젝트가 생성되는 것을 볼 수 있는데(싱글톤 레지스트리),
이는 스프링이 주로 적용되는 대상이 자바 엔터프라이즈 기술을 사용하는 서버환경이기 때문이라고 설명하고 있다.
(서버 환경에서는 싱글토의 사용이 권장됨)
또한 자바의 기본 싱글톤 패턴 구현은 여러 단점이 있기 때문에 스프링은 직접 싱글톤 형태의 오브젝트를 관리하는 기능을 제공한다.
스프링 빈 스코프: 빈이 생성되고 존재하고, 적용되는 범위
- 기본은 싱글톤(컨테이너 내 한개, 컨테이너가 존재하는 한 유지)
- 그 외 프로토 타입, 요청, 세션 등 있음(10장에서 자세한 설명)
IoC의 대표적인 동작원리 - DI
DI(의존관계 주입)
- 자신이 사용할 오브젝트에 대한 선택과 생성 제어권을 외부로 넘겨 자신은 수동적으로 주입받은 오브젝트를 사용
- 어떤 오브젝트가 이용할 오브젝트를 프로퍼티에 설정
- 객체의 실체를 외부환경설정(xml, 어노테이션 등)에서 컨트롤 할 수 있도록 하는 것
DI(의존관계 주입)를 통해 모듈간 결합도를 낮춰서 유연한 변경이 가능해진다.
스프링은 DaoFactory와 같은 자바클래스 외에도 다양한 방법들을 통해 DI의존관계 설정 정보를 만들 수 있는데, 책에서는 대표적으로 XML을 이용한 설정을 소개하고 있다.
장점
- XML은 텍스트파일이기 때문에 다루기 쉽다.
- 쉽게 이해 할 수 있다.
- 컴파일과 같은 별도의 빌드 작업이 필요 없다.
- 스키마나 DTD를 이용해 정해진 포멧에 따라 작성되었는지 확인 가능하다.
@Configuration -> <beans>
@bean -> <bean>
스프링이란 '어떻게 오브젝트가 설계되고, 만들어지고, 어떻게 관계를 맺고 사용되는지에 관심을 갖는 프레임워크' 라는 사실을 기억하자.
스프링의 관심은 오브젝트와 그 관계다.
//////////////////////////////////////////////////////////////////////////////////////////////
도서관에서 책을 빌렸다.
차근차근 정리해보자!!
1. 오브젝트와 의존관계
1장에서는 스프링이 어떤 것이고, 무엇이을 제공하는지보다는 오브젝트의 설계과 구현, 동작원리에 더 집중해보도록 하자.
스프링을 이해하려면 오브젝트에 깊은 관심을 가져야한다. 이러한 오브젝트에 대한 관심은 오브젝트의 기술적인 특징과 사용 방법을 넘어서 오브젝트의 설계로 발전한다.
**책에서는 간단하고 문제가 많은 DAO코드를 예시를 주고 이를 계속 개선, 수정하면서 그에 해당하는 개념을 설명하는 방식으로 설명하는 듯 싶음
1.1 초난감 DAO
DAO(Data Access Object)란?
DB를 사용해 데이터를 조회하거나 조작하는 기능을 전담하도록 만든 오브젝트
자바빈(JavaBean)이란?
자바빈은 원래 비주얼 툴에서 조작 가능한 컴포넌트를 말한다. 자바의 주력 개발 플랫폼이 웹 기반의 엔터프라이즈 방식으로 바뀌면서 비주얼 컴포넌트로서 자바빈은 인기를 잃어갔지만 자바빈의 몇 가지 코딩 관례는 JSP 빈, EJB와 같은 표준 기술과 자바빈 스타일의 오브젝트를 사용하는 오픈소스 기술을 통해 게속 이어져 왔다. 이제는 자바빈이라고 말하면 비주얼 컴포넌트라기 보다는 다음 두 가지 관례를 따라 만들어진 오브젝트를 가리킨다. 간단히 빈이라고 부르기도 한다.
-디폴트 생성자: 자바빈은 파라미터가 없는 디폴트 생성자를 갖고 있어야 한다. 툴이나 프레임워크에서 리플렉션을 이용해 오브젝트를 생성하기 때문에 필요하다.
-프로퍼티: 자바빈이 노출하는 이름을 가진 속성을 프로퍼티라고 한다. 프로퍼티는 set으로 시작하는 수정자 메소드(setter)와 get으로 시작하는 접근자 메소드(getter)를 이용해 수정 또는 조회할 수있다.
1.2 DAO의 분리
프로그래밍의 기초 개념 중에 관심사의 분리(Separation of Concerns)이라는 게 있다. 이를 객체지향에 적용해보면, 관심이 같은 것끼리는 하나의 객체 안으로 또는 친한 객체로 모이게하고, 관심이 다른 것은 가능한 한 따로 떨어져서 서로 영향을 주지 않도록 분리하여는 것이라 생각할 수 있다.
리펙토링이란?
기존의 코드를 외부의 동작방식에는 변화 없이 내부 구조를 변경해서 재구성하는 작업 또는 기술을 말한다. 리펙토링을 하면 코드 내부의 설계가 개선되어 코드를 이해하기가 더 편해지고, 변화에 효율적으로 대응할 수 있다. 결국 생산성은 오라가고, 코드의 품질은 높아지며, 유지보수하기 용이해지고, 견고하면서도 유연한 제품을 개발할 수 있다. 대표적으로 중복된 코드 제거가 있다.
템플릿 메소드 패턴이란?
상속을 통해 슈퍼클래스의 기능을 확장할 때 사용하는 가장 대표적인 방법이다. 변하지 않는 기능을 슈퍼클래스에 만들어두고 자주 변경되며 확장할 기능은 서브클래스에서 만들도록 한다. 슈퍼클래스에서는 미리 추상 메소드 또는 오버라이드 가능한 메소드를 정의해두고 이를 활용해 코드의 기본 알고리즘을 담고 있는 템플릿 메소드를 만든다. 슈퍼클래스에서 디폴드 키능을 정의해두거나 비워뒀다가 서브클래스에서 선택적으로 오버라이드할 수 있도록 만들어둔 메소드를 훅 메소드라고 한다. 서브클래스에서는 추상 메소드를 구현하고나, 훅 메소드를 우버라이드하는 방법을 이용해 기능의 일부를 확장한다.
펙토리 메소드 패턴이란?
펙토리 메소드 패턴도 템플릿메소드 패턴과 마찬가지로 상속을 통해 기능을 확장하게 하는 패턴이다. 그래서 구조도 비슷하다. 슈퍼클래스 코드에서도 서브클래스에서 구현할 메소드를 호출해서 필요한 타입의 오브젝트를 가져와 사용한다. 이 메소드는 주로 인터페이스 타입으로 오브젝트를 리턴하므로 서브클래스에서 정호가히 어떤 클래스의 오브젝트를 만들어 리턴할지는 슈퍼크래스에서는 알지 못한다. 사실 관심도 없다. 서브 클래스는 다양한 방법으로 오브젝트를 생성할 수 있도록 미리 정의해둔 메소드를 펙토리 메소드라고 하고, 이 방식을 통해 오브젝트 생성 방법을 나머지 로직, 즉 슈퍼클래스의 기본 코드에서 독립시키는 방법을 펙토리 메소드 패턴이라고한다, 자바에서는 종종 오브젝트를 생성하는 기능을 가진 메소드를 일반적으로 펙토리 메소드라고 부르기도 한다, 이때 말하는 펙토리 메소드와 펙토리 메소드 패턴의 펙토리 메소드는 의미가 다르므로 혼동하지 않도록 주의해야 한다.
//이 부분 다시 정리 할 것
>>이 템플릿 메소드 패턴이나 팩토리 메소드 패턴으로 관심사사힝 다른 코드를 분리하고 서로 독립적으로 변경, 확장할 수 있도록 만드는 것은 효과적이지만 상속을 사용했다는 단점이 있다.
>>상속 자체는 간단해 보이고 사용하기도 편리하게 느껴지지만 사실 많은 한계점이 있다.
>>자바는 다중상속을 지원하지 않기 때문에 상속 후 다른 목적으로 상속을 적용하기 힘들기 때문??
1.3 DAO의 확장
독립적인 클래스를 만들어 클래스를 분리하여 확장할 수 있다. 하지만 이런식으로 사용하면 다른 환경에 맞게 구현해서 쓸 수 있는 자유로운 확장이 불가능 하다.
그렇기 때문에 두 개의 클래스가 서로 긴밀하게 연결되어 있지 않도록 중간에 추상적인 연결고리를 만들어주는 방법으로 해결할 수 있다. >> 인터페이스
개방 폐쇄의 원칙이란?
깔끔한 설게를 위한 적용 가능한 객체지향 설계 원칙 중 하나로, '클래스나 모듈은 확장에는 열려 있어야 하고 변경에는 닫혀 있어야 한다.' 라는 의미이다. 잘 설계된 객체 지향 클래스의 구조를 살펴보면 이 원칙을 잘 지키고 있다.(인터페이스를 사용해 확장 기능을 정의한 대부분의 API)
>> 개방 폐쇄 원칙은 높은 응집도와 낮은 결합도라는 원리로도 설명 가능함.
높은 응집도란, 변경이 일어날 때 모듈의 많은 부분이 함께 바뀐다는 것이다. 만약 모듈의 일부분에만 변경이 일어나도 된다면, 모듈 전체에서 어떤 부분이 바뀌어야 하는지 파악해야 하고, 또 그변경으로 인해 바뀌지 않은 부분에는 다른 영향을 미치지 않는지 확인해야 하는 이중의 부담이 생긴다.
낮은 결합도란, 관계를 유지하는 데 꼭 필요한 최소한의 방법만 간접적인 형태로 제공하고, 나머지는 서로 독립적이고 알 필요도 없게 만들어주는 것이다. 결합도가 낮아지면 변화에 대응하는 속도가 높아지고, 구성이 깔끔해진다. 또한 확장하기 편해짐
>>결국 하나의 변경이 발생할 때 모듈과 객체로 변경에 대한 요구가 전파되지 않은 상태
객체지향 설계 원칙(SOLID)이란?
오랜 시간 동안 객체지향 설계에 관한 여러가지 원리와 원칙을 체계적으로 잘 정리한 것으로, 로버트 마틴이 정리하였다. SOLID는
SRP(The Single Responsibility Principle): 단일 책임 원칙
OCP(The Open Closed Principle): 개방 폐쇄 원칙
LSP(The Liskov Substitution Principle): 리스코프 치환 원칙
ISP(The Interface Segregation Principle): 인터페이스 분리 원칙
DIP(The Dependency Inversion Principle): 의존관계 역전 원칙
전락패턴이란?
자신의 기능 맥락에서, 필요에 따라 변경이 필요한 알고리즘을 인터페이스를 통해 통째로 외부로 분리시키고, 이를 구현한 구체적인 알고리즘을 클래스를 필요에 따라 바꿔서 사용할 수 있게하는 디자인 패턴
>> 스프링은 지금까지 언급한 객체지향적 설계 원칙과 디자인 패턴에 나타난 장점을 자연스럽게 개발자들이 활용할 수 있게 해주는 프레임워크이다.
1.4 제어와 역전(IoC, Inversion of Control)
IoC는 프로그램의 제어 흐름 구조가 뒤바뀌는 것이라고 설명할 수 있다.
//추가정리 필요
1.5 스프링의 IoC
빈(bean): 스프링이 제어권을 가지고 직접 만들고 관계를 부여하는 오브젝트
빈펙토리(bean factory): 빈의 생성과 관계 설정과 같은 제어를 담당하는 IoC 오브젝트 보통 빈 팩토리보다는 이를 좀 더 확장한 애플리케이션 컨텍스트를 주로 사용함
(빈 팩토리라고 할때는 빈을 생성하고 관게를 설정하는 IoC의 기본 기능에 초점을 맞춘 것이고, 에플레케이션 컨텍스트라고 말할 때는 애플리케이션 전반에 걸쳐 모든 구성요소의 제어 작업을 담당하는 IoC 엔진이라는 의미가 좀 더 부각된다 보면 된다.)
애플리케이션 컨텍스트: 빈의 생성, 관계설정 등의 제어 작업을 총괄(IoC컨테이너라고도 하고, 스프링컨테이너, 빈 팩토리라고도 부름?)>>스프링의 가장 대표적인 오브젝트
애플리케이션 컨텍스트를 사용했을 때 얻을 수 있는 장점
클라이언트는 구체적인 팩토리 클래스를 알 필요가 없다
>>오브젝트 텍토리가 아무리 많아져도 이를 알아야하거나 직접 사용할 필요 없고, 일관된 방식으로 원하는 오브젝트를 가져올 수 있다.
애플리케이션 컨텍스트는 종합 IoC 서비스를 제공해준다.
>>오브젝트가 만들어지는 방식, 시점과 전략을 다르게 가져갈 수도 있고, 부가적으로 자동생성, 오브젝트에 대한 후처리, 정보의 조합, 설장방식의 다변화 ,인터셉팅 등 오브젝트를 효과적으로 활용할 수 있는 다양한 기능을 제공한다. 또한 빈이 사용할 수 있는 기반기술 서비스나 외부 시스템과의 연동 등을 컨테이너 차원에서 제공해주기도 한다.
애플리케이션 컨텍스트는 빈을 검색하는 다양한 방법을 제공해준다.
>>getBean()메소드는 빈의 이름을 이용해 빈을 찾아준다. 타입믄으로 빈을 검색하거나 특별한 어노테이션 설정이 되어 있는 빈을 찾을 수도 있다.
스프링 IoC의 용어 정리
빈: 스프링이 IoC방식으로 관리하는 오브젝트. 주의할 점은 스프링을 사용하는 애플리케이션에서 만들어지는 모든 오브젝트가 다 빈은 아니라는 사실이다. 그중에서 스프링이 직접 생성과 제어를 담당하는 오브젝트만을 빈이라 부른다.
빈 팩토리: 스프링의 IoC를 담당하는 핵심 컨테이너. 빈을 등록하고, 생성하고, 조회하고 돌려주고, 그 외 부가적인 빈을 관리하는 기능을 담당. 보통 바로 사용하지 않고 이를 확장한 애플리케이션 컨텍스트를 이용함. BeanFactory라고 붙여쓰면 빈 팩토리가 구현하고 있는 가장 기본적인 인터페이스의 이름이 됨. getBean()과 같은 메소드가 정의되어 있다.
애플리케이션 컨텍스트: 빈 팩토리를 확장한 IoC컨테이너. 빈을 등록하고 관리하는 기본적인 기능은 빈 팩토리와 동일. 여기에 스프링이 제공하는 각종 부가서비스를 추가로 제공함
설정정보/설정 메타정보(configuration metadata): 애플리케이션 컨텍스트 또는 빈 팩토리가 IoC를 적용하기 위해 사용하는 메타 정보를 말함. 실제로 스프링의 설정 정보는 컨테이너에 어떤 기능을 세팅하거나 조정하는 경우에도 사용하지만, 그보다는 IoC컨테이너에 의해 관리되는 애플리케이션 오브젝트를 생성하고 구성할 때 사용됨. 애플리케이션 형상 정보라고 부르기도 함.
컨테이너 또는 IoC컨테이너: IoC방식으로 빈을 관리한다는 의미에서 애플리케이션 컨텍스트나 빈 팩토리를 컨테이너 또는 IoC컨테이너 라고도 함.
스프링 프레임워크: IoC컨테이너, 애플리케이션 컨텍스트를 포함해서 스프링이 제공하는 모든 기능을 통틀어 말할 떄 주로 사용함.
1.6 싱글톤 레지스트리와 오브젝트 스코프
오브젝트의 동일성과 동등성
동일성 ==, 하나의 오브젝트만 존재하는 것이고 두 개의 오브젝트 레퍼런스 변수를 가짐
동등성 equals(), 두개의 각기 다른 오브젝트가 메모리상에 존재, 오브젝트 동등성 기준에 따라 두 오브젝트의 정보가 동등하다고 판단되는 것
싱글톤 패턴(Singleton Pattern)이란?
GoF가 소개한 디자인 패턴중 하나로 가장 자주 활용되는 패턴이기도 하지만 가장 많은 비판을 받는 패턴이기도 함.
어떤클래스를 애플리케이션 내에서 제한된 인스턴스 개수, 이름처럼 주로 하나만 존재하도록 강제하는 패턴. 이렇게 하나만 만들어지는 클래스의 오브젝트는 애플리케이션 내에이서 전역적으로 접근이 가능함. 단일 오브젝트만 존재해야하고, 이를 애플리케이션의 여러 곳에서 공유하는 경우에 주로 사용함.
자바에서 싱글톤을 구현하는 방법
-클래스 밖에서는 오브젝트를 생성하지 못하도록 생성자를 private으로 만든다.
-생성된 싱글톤 오브젝트를 저장할 수 있는 자신과 같은 타입의 스태틱필드를 정의한다.
-스태틱 펙토리 메소드인 getInstence()를 만들고 이 메소드가 최초로 호출되는 시점에서 한 번만 오브젝트가 만들어지게 한다
-한번 오브젝트(싱글톤)가 만들어지고 난 후에는 getInstence() 메소드를 통해 이미 만들어져 스태틱 필드에 저장해둔 오브젝트를 넘겨준다.
싱글톤 패턴 구현방식의 문제점
-private 생성자를 갖고 있기 떄문에 상속할 수 없음.
-싱글톤은 테스트하기가 힘들다
-서버환경에서는 싱글톤이 하나만 만들어지는 것을 보장하지 못한다.
(자바 언어를 이용한 싱글톤 패턴 기법은 서버환경에서는 싱글톤이 꼭 보장된다고 볼 수 없음)
-싱글톤의 사용은 전역 상태를 만들 수 있기 때문에 바람직하지 못하다.
싱글톤 레지스트리
자바의 기본적인 싱글톤 패턴의 구현 방시기은 여러가지 단점이 있기 때문에, 스프링은 직접 싱글톤 형태의 오브젝트를 만들어 관리하는 기능을 제공
-장점은 스태틱 메소드와 private 생성자를 사용해야하는 비정상적인 클래스가 아니라 평범한 자바 클래스를 싱글톤으로 활용하게 해준다는 점.
-싱글톤은 멀티스레드 환경이라면 여러 스레드가 동시에 접근해서 사용할 수 있기 때문에 조심해야 함. 상태정보를 내부에 갖고 있지 않는 무정부(stateless)방식으로 만들어져야 함.
-다중 사용자의 요청을 한꺼번에 처리하는 스레드들이 동시에 싱글톤 오브젝트의 인스턴스 변수를 수정하는 것은 매우 위험함.>> 저장할 공간이 하나뿐이니 서로 값을 덮어쓰고 자신이 저자앟지 않은 값을 읽어올 수 있기 때문
따라서 싱글톤은 기본적으로 인스턴스 필드의 값을 변경하고 유지하는 상태유지(stateful) 방식으로 만들지 않는다.
스프링 빈의 스코프
스코프: 스프링이 관리하고 오브젝트, 즉 빈이 생성된고, 존재하고 적용되는 범위
스코프의 종류
-싱글톤 스코프: 컨테이너 내에 한 개의 오브젝트만 만들어져서, 강제로 제거하지 않는 한 스프링 컨테이너가 존재하는 동안 계속 유지됨. 스프링에서 만들어지는 대부분의 빈은 싱글톤스코프임.
-프로토타입 스코프: 싱글톤과 달리 컨테이너에 빈을 요청할 때마다 매번 새로운 오브젝트를 만들어줌.
-요청(request) 스코프: 웹을 통해 새로운 HTTP 요청이 생길때마다 생성
-세션(session) 스코프: 웹의 세션과 유사
1.7 의존관계 주입(DI)
의존관계 주입, 의존성 주입, 의존 오브젝트 주입?
Dependency Injection는 오브젝트 레퍼런스를 외부로부터 제공(주입)받고 이를 통해 여타 오브젝트와 다이내믹하게 의존관계가 만들어지는 것이 핵심이다. 그렇기에 책에선 의존관계 주입이라 사용한다.
>>의존관계를 런타임시에 연결해주는 작업
의존 관계주입이란 다음 세가지 조건을 충족하는 작업
-클래스 모델이나 코드에는 런타임 시점의 의존관계가 드러나지 않는다. 그러기 위해서는 인터페이스에만 의존하고 있어야 한다.
-런타임 시점의 의존관계는 컨테이너나 팩토리 같은 제3의 존재가 결정한다.
-의존관계는 사용할 오브젝트에 대한 레퍼런스를 외부에서 제공(주입)해줌으로써 만들어진다.
의존관계 검색(dependency lookup)
의존관계를 맺는 방법이 외부로부터의 주입이 아니라 스스로 검색을 이용
getBean()메소드를 통해 객체를 검색하여 받아옴
1.8 XML을 이용한 설정
스프링은 자바클래스를 이용하는 것 외에도, 다양한 방법을 통해 DI의존관계 설정정보를 만들 수 있는데 대표적인 것이 XML이다. XML은 텍스트파일이기 때문에 다루기 쉽고, 컴파일과 같은 별도의 빌드작업이 없다는 것이 장점이다.
XML설정
스프링 애플리케이션 컨텍스트는 XML에 담긴 DI정보를 활용할 수 있다. DI정보가 담긴 XML파일은 <beans>를 루트 엘리먼트로 사용한다.
빈의 DI정보
-빈의 이름
-빈의 클래스: 빈 오브젝트를 어떤 클래스를 이용해서 만들지를 정의
-빈의 의존 오브젝트: 빈의 생성자나 수정자 메소드를 통해 의존 오브젝트를 넣어줌.
클래스 설정과 XML 설정의 대응항목
자바 XML 설정 정보
빈 설정파일 @Configuration <beans>
빈의 이름 @Bean methodNames <bean id="methodName"
빈의 클래스 return new BeanClass() class-"a.b.c...BeanClass">
XML에서는 <property>태그를 사용해 의존 오브젝트와의 관계 정의한다.
DTD와 스키마
XML 문서는 미리 정해진 구조를 따라서 작성됐는지 검사할 수 있다. 구조를 정의하는 방법에는 DTD와 스키마(schema)가 있는데, 스프링 XML 설정파일은 두 가지 방식 모두 지원한다.
-DTD를 사용할 경우
<beans>엘리먼트 앞에 다음와 같은 선언을 넣어준다.
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN 2.0//EN" "http://www.springframework.org/dtd/spring-beans-2.0.dtd">
-스키마는 DI를 위한 기본태그 <beans>, <bean> 외에도 특별한 목적을 위해 별도의 태그를 사용할 수 있는 방법을 제공한다. 특별한 이유가 없으면 스키마를 사용하는 것이 바람직함.
ex)내가 쓴 applicationcontext.xml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
|
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:p="http://www.springframework.org/schema/p"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
http://www.springframework.org/schema/jdbc
http://www.springframework.org/schema/jdbc/spring-jdbc-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-4.0.xsd">
<context:property-placeholder location="classpath*:application-properties.xml"/>
<context:annotation-config />
<!-- 데이터 부분 -->
<bean id="dataSource"
class="org.springframework.jdbc.datasource.SimpleDriverDataSource">
<property name="driverClass" value="com.mysql.jdbc.Driver"></property>
<property name="url" value="jdbc:mysql://localhost:3306/cot_pr1"></property>
<property name="username" value="root"></property>
<property name="password" value="123321"></property>
</bean>
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="configLocation" value="classpath:mybatis-config.xml" />
</bean>
<bean id="sqlSession" class="org.mybatis.spring.SqlSessionTemplate">
<constructor-arg index="0" ref="sqlSessionFactory"></constructor-arg>
</bean>
<bean id="UserDao" class="net.cot_pr1.dao.UserDao"
p:sqlSession-ref="sqlSession"
p:dataSource-ref="dataSource" />
<bean id="webBoardDao" class="net.cot_pr1.dao.WebBoardDao"
p:sqlSession-ref="sqlSession"
p:dataSource-ref="dataSource" />
<bean id="webReplyDao" class="net.cot_pr1.dao.WebReplyDao"
p:sqlSession-ref="sqlSession"
p:dataSource-ref="dataSource" />
<bean id="galleryDao" class="net.cot_pr1.dao.GalleryDao"
p:sqlSession-ref="sqlSession"
p:dataSource-ref="dataSource" />
<bean id="freeboardDao" class="net.cot_pr1.dao.FreeBoardDao"
p:sqlSession-ref="sqlSession"
p:dataSource-ref="dataSource" />
<bean id="freereplyDao" class="net.cot_pr1.dao.FreeReplyDao"
p:sqlSession-ref="sqlSession"
p:dataSource-ref="dataSource" />
<bean id="noticeDao" class="net.cot_pr1.dao.NoticeDao"
p:sqlSession-ref="sqlSession"
p:dataSource-ref="dataSource" />
<bean id="noticereplyDao" class="net.cot_pr1.dao.NoticeReplyDao"
p:sqlSession-ref="sqlSession"
p:dataSource-ref="dataSource" />
<bean id="qnaDao" class="net.cot_pr1.dao.QnADao"
p:sqlSession-ref="sqlSession"
p:dataSource-ref="dataSource" />
<bean id="qnareplyDao" class="net.cot_pr1.dao.QnAReplyDao"
p:sqlSession-ref="sqlSession"
p:dataSource-ref="dataSource" />
<bean id="adminDao" class="net.cot_pr1.dao.AdminDao"
p:sqlSession-ref="sqlSession"
p:dataSource-ref="dataSource" />
<!-- 파일업로드를 위한 디렉토리 설정 -->
<!-- String uploadPath = new String("업로드 경로") -->
<bean id="uploadPath" class="java.lang.String">
<!-- 파일업로드 디렉토리 -->
<constructor-arg value="C:\Users\SK\git\Cot_pr1\Cot_Pr1\src\main\webapp\resources\uploads" />
</bean>
<bean id="uploadPath2" class="java.lang.String">
<!-- 파일업로드 디렉토리 -->
<constructor-arg value="C:\Users\SK\git\Cot_pr1\Cot_Pr1\src\main\webapp\resources\profile" />
</bean>
<!-- 메일보내기 -->
<bean id="mailSender" class = "org.springframework.mail.javamail.JavaMailSenderImpl">
<property name="host" value="smtp.gmail.com" />
<property name="port" value="587" />
<property name="username" value="--@gmail.com" />
<property name="password" value="--" />
<property name="javaMailProperties">
<props>
<prop key="mail.transport.protocol">smtp</prop>
<prop key="mail.smtp.auth">true</prop>
<prop key="mail.smtp.starttls.enable">true</prop>
<prop key="mail.debug">true</prop>
</props>
</property>
</bean>
</beans>
| cs |
1장을 끝내기 전에, 스프링이란 '어떻게 오브젝트가 설계되고, 만들어지고, 어떻게 관계를 맺고 사용되는지에 관심을 갖는 프레임워크' 라는 사실을 기억하자. 스프링의 관심은 오브젝트와 그 관계다.
//////////////////////////////////
ㅜㅜㅜ어렵다 책 1회독으로 안될듯 장기간적으로 봐야하나..ㅠㅠ