본문 바로가기

Spring

토비의 스프링 1장 - 오브젝트와 의존관계

책의 정리 내용

- 책임이 다른 코드는 분리한다. 관심사별로 클래스를 나누기

- 그 중에서, 추후 수정이 있을것 같은 클래스는 인터페이스로 구현해서, 인터페이스의 정의부와 구현부로 나눈다

 > 이렇게 하면 인터페이스의 구현부가 달라지더라도, 이 인터페이스를 참고하는 쪽에서는 수정할 부분이 없기때문(전략패턴)

- 결국 한쪽의 기능 변화가 다른쪽의 변경을 요구하지 않아도 되게 했고(낮은 결합도), 자신의 책임과 관심사에만 순수하게 집중하는(높은 응집도) 깔끔한 코드를 만들 수 있다

- 오브젝트가 생성되고 여타 오브젝트와 관계를 맺는 작업의 제어권을 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