책의 정리 내용
- 책임이 다른 코드는 분리한다. 관심사별로 클래스를 나누기
- 그 중에서, 추후 수정이 있을것 같은 클래스는 인터페이스로 구현해서, 인터페이스의 정의부와 구현부로 나눈다
> 이렇게 하면 인터페이스의 구현부가 달라지더라도, 이 인터페이스를 참고하는 쪽에서는 수정할 부분이 없기때문(전략패턴)
- 결국 한쪽의 기능 변화가 다른쪽의 변경을 요구하지 않아도 되게 했고(낮은 결합도), 자신의 책임과 관심사에만 순수하게 집중하는(높은 응집도) 깔끔한 코드를 만들 수 있다
- 오브젝트가 생성되고 여타 오브젝트와 관계를 맺는 작업의 제어권을 IoC(Inversion of Control) 컨테이너로 넘겨서 오브젝트가 자신이 사용할 대상의 생성이나 선택에 관함 책임으로부터 자유롭게 만들어 줬다
- 전통적인 싱글톤 패턴 구현방식의 단점을 살펴보고, 서버에서 사용되는 서비스 오브젝트로서의 장점을 살릴 수 있는 싱글톤을 사용하면서도 싱글톤 패턴의 단점(어떤것이 있을까)을 극복할 수 있도록 설계된 컨테이너를 활용할 수 있다(싱글톤 레지스트리)
- DI(Data Injection)은 설계시점과 코드에는 클래스와 인터페이스 사이의 느슨한 의존관계만 만들어 놓고, 런타임시에 실제 사용할 구체적인 의존 오브젝트를 제 3자(DI 컨테이너)의 도움으로 주입받아서 다이내믹한 의존관계를 갖게 해준다
- XML을 이용해 DI 설정정보를 만들고, 의존 오브젝트가 아닌 일반값을 외부에서 설정해서 런타임시에 주입이 가능하다
중요한 Point => 스프링이란 '어떻게 오브젝트가 설계되고 만들어지고, 어떻게 관계를 맺고 사용되는지에 관심을 갖는 프레임워크' 이라는것을 꼭 기억하자!
아래는 내가 추가로 정리한 것
싱글톤 레지스트리
(쉬어가기) 싱글톤 패턴의 단점
- private 생성자를 갖고 있기 때문에 상속할 수 없다
- 싱글톤은 테스트하기가 힘들다
- 싱글톤은 만들어지는 방식이 제한적이기 때문에 테스트에서 사용될 때, 목 오브젝트 등으로 대체하기가 힘듬
- 서버환경에서는 싱글톤이 하나만 만들어지는 것을 보장하지 못한다
- 여러 개의 JVM에 분산돼서 설치가 되는 경우, 각각 독립적으로 오브젝트가 생기기 때문에 싱글톤으로서의 가치가 떨어진다 (jvm..이해 필요)
- 싱글톤의 사용은 전역상태를 만들 수 있기 때문에 바람직하지 못하다
그래서, 스프링의 싱글톤은 어떤 방식이란 말인가?
> 스프링은 직접 싱글톤 형태의 오브젝트를 만들고, 관리하는 기능을 제공한다(싱글톤 레지스트리)
> 싱글톤 레지스트리를 통해, private 생성자를 사용해야 하는 클래스가 아닌, 그 외 클래스들도 싱글톤으로 활용하게 해줌
> 평범한 자바 클래스라도 IoC 방식의 컨테이너를 사용해서 생성과 관계설정, 사용 등에 대한 제어권을 컨테이너에게 넘기면 손쉽게 싱글톤 방식으로 만들어져 관리되게 할 수 있다.
> 오브젝트 생성에 관한 모든 권한은 IoC 기능을 제공하는 애플리케이션 컨텍스트에게 있기 때문이다
>>> 결론은 IoC 컨테이너가, 싱글톤 처럼 객체를 관리한다는 뜻 같다!
스프링 빈의 스코프
빈의 스코프 란? 빈이 생성되고, 존재하고, 적용되는 범위를 말한다.
스프링 빈의 기본 스코프는 싱글톤이다. 싱글톤 스코프는 컨테이너 내에 한 개의 오브젝트만 만들어져서, 강제로 제거하지 않는 한 스프링 컨테이너가 존재하는 동안 계속 유지된다.
경우에 따라서는 싱글톤 외의 스코프를 가질 수 있다.(프로토타입 스코프, 요청 스코프, 세션 스코프)
프로토 타입은 싱글톤과 달리 컨테이너에 빈을 요청할 때 맏다 매번 새로운 오브젝트를 만들어 준다.
XML 설정 방법
자바 클래스에서 설정하는 것과 비교하면, 아래와 같이 맵핑된다
자바 코드 설정 정보 | XML 설정 정보 | |
빈 설정파일 | @Configuration | <beans> |
빈의 이름 | @Bean methodName() | <bean id="methodName" |
빈의 클래스 | return new BeanClass(); | class="package.path.BeanClass"> |
수정자 메소드 | object.setMethodName(InjectionObject); | <property name="MethodName" |
수정자 메소드의 파라메터(주입되는 의존 객체) | object.setMethodName(InjectionObject); | ref="InjectionObject"> |
수정자 메소드의 파라메터(값인 경우) | object.setMethodName(value) | value="value"> |
예를 들어 아래와 같은 XML 설정 정보가 있다.
<beans>
<bean id="dataSource" class="org.springframework.jdbc.datasource.SimpleDriverDataSource">
<property name="driverClass" value="com.mysql.jdbc.Driver" />
<property name="url" value="jdbc:mysql://localhost/spring" />
<property name="username" value="spring" />
<property name="password" value="password" />
</bean>
<bean id="userDao" class="package.path.dao.UserDao">
<property name="dataSource" ref="dataSource" />
</bean>
</beans>
이를 보고, 아래와 같이 해석할 수 있다.
- Bean 객체가 2개가 있다.
> dataSource 라는 객체는, SimpleDriverDataSource Type의 오브젝트를 반환하는 친구구나!
> userDao 라는 객체는, UserDao Type의 오브젝트를 반환하는 친구구나!
- 각각 Bean의 수정자 메소드를 아래와 같이 이해할 수 있다.
> dataSource 객체는 setDriverClass(), setUrl(), setUsername(), setPassword()의 수정자 메소드를 갖고 있구나!
> 얘네는 각각 "com.mysql.jdbc.Driver", "jdbc:mysql://...", "spring", "password"라는 값을 파라메터로 주입되구나!
> userDao 객체는 setDatasource()라는 수정자 메소드를 갖고 있고, 이놈의 파라메터로 dataSource()를 통한 의존
객체가 전달 되는구나!
'Spring' 카테고리의 다른 글
AbstractRoutingDataSource (0) | 2020.01.28 |
---|---|
QueryDSL (0) | 2020.01.28 |
Spring Cloud Data Flow (0) | 2020.01.06 |
토비의 스프링 2장 - 테스트 (0) | 2019.06.02 |