From c73502bb4550025752428bb36092cab8e1a76b94 Mon Sep 17 00:00:00 2001 From: Hyeongwon-up Date: Mon, 1 Nov 2021 17:45:23 +0900 Subject: [PATCH 1/2] =?UTF-8?q?0=EC=A3=BC=EC=B0=A8=20=EC=A0=95=EB=A6=AC=20?= =?UTF-8?q?-=20=EC=9D=B4=ED=98=95=EC=9B=90?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...1_\354\235\264\355\230\225\354\233\220.md" | 204 ++++++++++++++++++ 1 file changed, 204 insertions(+) create mode 100644 "1\354\236\245_\354\230\244\353\270\214\354\240\235\355\212\270\354\231\200_\354\235\230\354\241\264\352\264\200\352\263\204/1\354\236\245_\354\230\244\353\270\214\354\240\235\355\212\270\354\231\200_\354\235\230\354\241\264\352\264\200\352\263\204/\354\230\244\353\270\214\354\240\235\355\212\270\354\231\200 \354\235\230\354\241\264\352\264\200\352\263\2041_\354\235\264\355\230\225\354\233\220.md" diff --git "a/1\354\236\245_\354\230\244\353\270\214\354\240\235\355\212\270\354\231\200_\354\235\230\354\241\264\352\264\200\352\263\204/1\354\236\245_\354\230\244\353\270\214\354\240\235\355\212\270\354\231\200_\354\235\230\354\241\264\352\264\200\352\263\204/\354\230\244\353\270\214\354\240\235\355\212\270\354\231\200 \354\235\230\354\241\264\352\264\200\352\263\2041_\354\235\264\355\230\225\354\233\220.md" "b/1\354\236\245_\354\230\244\353\270\214\354\240\235\355\212\270\354\231\200_\354\235\230\354\241\264\352\264\200\352\263\204/1\354\236\245_\354\230\244\353\270\214\354\240\235\355\212\270\354\231\200_\354\235\230\354\241\264\352\264\200\352\263\204/\354\230\244\353\270\214\354\240\235\355\212\270\354\231\200 \354\235\230\354\241\264\352\264\200\352\263\2041_\354\235\264\355\230\225\354\233\220.md" new file mode 100644 index 0000000..fa54d31 --- /dev/null +++ "b/1\354\236\245_\354\230\244\353\270\214\354\240\235\355\212\270\354\231\200_\354\235\230\354\241\264\352\264\200\352\263\204/1\354\236\245_\354\230\244\353\270\214\354\240\235\355\212\270\354\231\200_\354\235\230\354\241\264\352\264\200\352\263\204/\354\230\244\353\270\214\354\240\235\355\212\270\354\231\200 \354\235\230\354\241\264\352\264\200\352\263\2041_\354\235\264\355\230\225\354\233\220.md" @@ -0,0 +1,204 @@ +# 1장 오브젝트와 의존관계 + +*** + +스프링은 자바를 기반으로 한 기술이다. +스프링을 이해하려면 먼저 오브젝트에 깊은 관심을 가져야 한다. +*** + +## 1.1 초난감 DAO + +DAO +> Data Access Object : DB를 사용해 데이터를 조회하거나 조작하는 기능을 전담하도록 만든 object. + + + +### JDBC를 이용하는 작업의 일반적인 순서 +1. DB 연결을 위한 connection 불러온다. +2. SQL을 담은 Statement 를 만든다. +3. 만들어진 statement 실행. +4. 조회의 경우 SQL 쿼리의 실행결과를 ResultSet으로 받아서 정보를 저장할 오브젝트에 옮겨준다. +5. 작업 중에 생성된 connection, statement, ResultSet 같은 리소스 작업을 마친 후 반드시 닫아준다. +6. JDBC API 가 만들어내는 예외를 잡아서 직접 처리하거나, 메소드에 throws를 선언해서 예외가 발생하는 메소드 밖으로 던지게 한다. + +*** + +## 1.2 DAO의 분리 + +*** + +### 관심사의 분리 + +- 개발자가 객체를 설계할 때 가장 염두에 둬야 할 사항은 바로 미래의 변화를 어떻게 대비할 것인가이다. +- 미래를 위해 설계하고 개발해야 한다. +- 객체지향 설게와 프로그래밍이 이전의 절차적 프로그래밍 패러다임에 비해 초기에 좀 더 많은, 번거러운 작업을 요구 -> 객체지향 기술 자체가 지니는, 변화에 효과적으로 대처할 수 있다는 기술적인 특징. + +### "분리"와 "확장"을 고려한 설계를 해야한다!! + + +## 분리 + +- 모든 변경과 발전은 한 번에 **한 가지 관심사항** 에 집중해서 일어난다. +- 문제는, 변화는 대체로 집중된 한 가지 관심에 대해 일어나지만 그에 따른 작업은 한 곳에 집중되지 않는 경우가 많다. + +### " 관심사의 분리 Separation of Concerns" + + +> 예시) DB 커넥션 분리-상속을 통한 분리 +> > ``` java +> > public abstract class UserDao { +> > +> > public void add(User user) throws ClassNotFoundException, SQLException {> > +> > Connection c = getConnection(); +> > ... +> > } +> > +> > public User get(String id) throws ClassNotFoundException, SQLException { +> > Connection C = getConnection(); +> > ... +> > } +> > +> > public abstact Connection getConnection() throws ClassNotFoundException, SQLException; +> > +> > } +> > +> > ``` +> > +> > ``` java +> > public class NUserDao extends UserDao { +> > +> > public Connection getConnection() throws ClassNotFoundException, SQLException { +> > //N사 DB connection 생성코드 +> > } +> > +> > public class DUserDao extends UserDao { +> > +> > public Connection getConnection() throws ClassNotFoundException, SQLException { +> > // D 사 DB connection 생성코드 +> > } +> > } + + + + +- **템플릿 메소드 패턴 (template method pattern )** +> 이렇게 슈퍼클래스에 기본적인 로직의 흐름을 만들고, 그 기능의 일부를 추상 메소드나 오버라이딩이 가능한 protected 메소드 등으로 만든 뒤 +서브클래스에서 이런 메소드를 필요에 맞게 구현해서 사용하도록 하는 방법을 + + +- **팩토리 메소드 패턴 (Factory Method Pattern)** + +> UserDao 의 서브클래스의 getConnection 메소드는 어떤 Connection 클래스의 오브젝트를 어떻게 생성할 것인지를 결정한다. 이렇게 서브클래스에서 구체적인 오브젝트 생성 방법을 결정하게 하는 방법 + + +*** + +## 1.3 DAO확장 +- 모든 오브젝트는 변화의 이유와 시기, 주기 등이 다르다. +*** +### 1.3.1 클래스의 분리 + +- 상속관계도 아닌 완전히 독립적인 클래스 + +> ``` java +> public abstract class UserDao { +> private SimpleConnectionMaker simpleConnectionMaker; +> +> public void add(User user) throws ClassNotFoundException, SQLException { +> +> ... +> } +> +> public User get(String id) throws ClassNotFoundException, SQLException { +> +> Connection c = simpleConnectionMaker.makeNewConnection(); +> +> ... +> +> } +> } +> + +> 독립시킨 DB 연결 기능 SimpleConnectionMaker +> ``` java +> public class SimpleConnectionMaker { +> public Connection makeNewConnection() throws ClassNotFoundException, SQLException { +> Class.forName("org.mariadb.jdbc.Driver"); +> Connection c = DriverManager +> .getConnection("jdbc:mysql://127.0.0.1:3306/springbook", "root", "password"); +> return c; +> } +> } + + +### 문제점 +- 상속처럼 자유로운 확장이 가능하게 하려면 DB 커넥션 메소드의 인터페이스가 동일해야한다. +- 커넥션을 제공하는 클래스의 이름을 구체적으로 알아야한다. + + + +### 1.3.2 인터페이스의 도입 + +- 두 개의 클래스가 서로 긴밀하게 연결되지 않도록 중간에 추상적인 연결고리 만들어주자! => 추상화 + +**추상화** +> 어떤 것들의 공통적인 성격을 뽑아내어 이를 따로 분리해내는 작업. + +**자바가 추상화를 위해 제공하는 가장 유용한 도구는 **인터페이스** 이다.** + +- 인터페이스를 사용하면 인터페이스의 메소드르 통해 알 수 있는 기능에만 관심을 가지면 되지, 그 기능을 어떻게 구현했는지에 관심을 둘 필요 없다. + + +> ConnectionMaker 인터페이스 +> ``` java +> public interface ConnectionMaker { +> public Connection makeConnection() throws ClassNotFoundException, SQLException; +> } +> + +> ConnectionMaker 구현체 +> ``` java +> public class DConnectionMaker implements ConnecctionMaker { +> ... +> public Connection makeConnection() throws ClassNotFoundException, SQLException { +> // D 사의 Connection 코드 +> } +> } + +> ConnectionMaker 인터페이스 사용하도록 구현한 UserDao구현체 +> ``` java +> public class UserDao { +> private ConnectionMaker connectionMaker; +> +> public UserDao() { +> connectionMaker = new DConnectionMaker(); +> } +> +> public void add(User user) throws ClassNotFoundException, SQLException { +> Connection c = connectionMaker.makeConnection(); +> ... +> } +> +> public User get(String id) throws ClassNotFoundException, SQLException { +> Connection c = connectionMaker.makeConnection(); +> ... +> +> } + + +### 문제점 +> connectionMaker = new DConnectionMaker(); +- UserDao 에 DConnection 클래스의 생성자를 호출해서 오브젝트를 생성하는 코드가 남아있다. +- UserDao 와 UserDao가 사용할 ConnectionMaker의 특정 구현 클래스 사이에 관계를 설정해주는 것에 관한 관심을 분리하자. + +> ``` java +> ... +> public static void main(String[] args) throws ClassNotFoundException, SQLException { +> +> ConnectionMaker connectionMaker = new DConnectionMaker(); +> +> UserDao dao = new UserDao(connectionMaker); +> ... +> +> } + From 710ee1866d34c014a552f243e6177d75a55a9a0a Mon Sep 17 00:00:00 2001 From: Hyeongwon-up Date: Mon, 8 Nov 2021 13:30:29 +0900 Subject: [PATCH 2/2] =?UTF-8?q?1=EC=A3=BC=EC=B0=A8=20=EC=A0=95=EB=A6=AC=20?= =?UTF-8?q?-=20=EC=9D=B4=ED=98=95=EC=9B=90?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...1_\354\235\264\355\230\225\354\233\220.md" | 273 ++++++++++++++++++ 1 file changed, 273 insertions(+) diff --git "a/1\354\236\245_\354\230\244\353\270\214\354\240\235\355\212\270\354\231\200_\354\235\230\354\241\264\352\264\200\352\263\204/1\354\236\245_\354\230\244\353\270\214\354\240\235\355\212\270\354\231\200_\354\235\230\354\241\264\352\264\200\352\263\204/\354\230\244\353\270\214\354\240\235\355\212\270\354\231\200 \354\235\230\354\241\264\352\264\200\352\263\2041_\354\235\264\355\230\225\354\233\220.md" "b/1\354\236\245_\354\230\244\353\270\214\354\240\235\355\212\270\354\231\200_\354\235\230\354\241\264\352\264\200\352\263\204/1\354\236\245_\354\230\244\353\270\214\354\240\235\355\212\270\354\231\200_\354\235\230\354\241\264\352\264\200\352\263\204/\354\230\244\353\270\214\354\240\235\355\212\270\354\231\200 \354\235\230\354\241\264\352\264\200\352\263\2041_\354\235\264\355\230\225\354\233\220.md" index fa54d31..1964c89 100644 --- "a/1\354\236\245_\354\230\244\353\270\214\354\240\235\355\212\270\354\231\200_\354\235\230\354\241\264\352\264\200\352\263\204/1\354\236\245_\354\230\244\353\270\214\354\240\235\355\212\270\354\231\200_\354\235\230\354\241\264\352\264\200\352\263\204/\354\230\244\353\270\214\354\240\235\355\212\270\354\231\200 \354\235\230\354\241\264\352\264\200\352\263\2041_\354\235\264\355\230\225\354\233\220.md" +++ "b/1\354\236\245_\354\230\244\353\270\214\354\240\235\355\212\270\354\231\200_\354\235\230\354\241\264\352\264\200\352\263\204/1\354\236\245_\354\230\244\353\270\214\354\240\235\355\212\270\354\231\200_\354\235\230\354\241\264\352\264\200\352\263\204/\354\230\244\353\270\214\354\240\235\355\212\270\354\231\200 \354\235\230\354\241\264\352\264\200\352\263\2041_\354\235\264\355\230\225\354\233\220.md" @@ -202,3 +202,276 @@ DAO > > } +*** + +### 1.3.4 원칙과 패턴. + +**객체 지향 설계 원칙 SOLID** +> SRP(Single Responsibility Principle) : 단일 책임 원칙 +> OCP(Open Closed Principle) : 개방 폐쇄 원칙 +> LSR(Liskov Substituition Principle) : 리스코프 치환 원칙 +> ISP(Interface Segeregtion Principle) : 인터페이스 분리 원칙 +> DIP(Dependency Inversion Principle) : 의존관계 역전 원칙 + + + +**개방 페쇄 원칙 OCP(Open-Closed Principle)** +- 깔끔한 설계를 위해 적용 가능한 객체지향 설계 원칙 중 하나이다. +- " 클래스나 모듈은 확장에는 열려 있어야 하고 변경에는 닫혀 있어야 한다." +- **인터페이스** 를 통해 제공되는 확장 포인트는 확장을 위해 개방되어 있지만, **인터페이스**를 이용하는 클래스는 자신의 변화가 불필요하게 일어나지 않도록 폐쇄. + + + +**높은 응집도와 낮은 결합도** + + +> 높은 응집도 +>- 응집도가 높다 => 하나의 모듈, 클래스가 하나의 책임 또는 관심사에만 집중되어 있다. + +> 낮은 결합도 +>- 책임과 관심사가 다른 오브젝트 또는 모듈과는 낮은 결합도, 즉 느슨한 연결 형태를 유지해야 한다. + + + +**전략 패턴 (Strategy Pattern)** +- 자신의 기능 맥락에서, 필요에 따라 변경이 필요한 알고리즘을 인터페이스를 통해 통째로 외부로 분리시키고, 이를 구현한 구체적인 알고리즘 클래스를 필요에 따라 바꿔서 사용할 수 있게 하는 **디자인 패턴** 이다. + +*** + +## 1.4 제어의 역전 (IOC) +- 일반적인 프로그램의 흐름 : main 메소드와 같이 프로그램이 시작되는 지점에서 다음에 사용할 오브젝트를 결정 -> 결정한 오브젝트 생성 -> 오브젝트에 있는 메소드 호출 등의 흐름이 반복된다. + +- 제어의 역전에서는 오브젝트가 자신이 사용할 오브젝트를 선택하지 않는다. 생성하지도 않고 어떻게 만들어지고 어디서 사용하는지 알 수 없다. + +### 프레임워크 VS 라이브러리 +- 라이브러리를 사용하는 어플리케이션 코드는 어플리케이션의 흐름을 직접 제어한다. +- 프레임워크는 거꾸로 어플리케이션의 코드가 프레임워크에 의해 사용된다. 어플리케이션 코드는 프레임워크가 짜놓은 틀에서 수동적으로 동작해야한다. + +*** + +## 1.5 스프링의 IoC + +### 1.5.1 오브젝트 팩토리를 이용한 스프링 IoC + +> 팩토리 +> - 객체의 생성방법을 결정하고, 그렇게 만들어진 오브젝트를 돌려주는 오브젝트. + +# 빈 bean + +- 스프링에서 스프링이 제어권을 가지고 직접 만들고 관계를 부여하는 오브젝트를 **빈** 이라고 한다. +- 동시에 스프링 빈은 스프링컨테이너가 생성과 관계설정, 사용 등을 제어해주는 제어의 역전이 적용된 오브젝트. + +> +>**빈 팩토리** +>>빈의 생성과 관계설정 같은 제어를 담당하는 IoC 오브젝트를 **빈 팩토리**라고 한다. +>>보통 빈 팩토리 보다는 이를 좀 더 확장한 **애플리케이션 컨테스트**를 주로 사용한다. + + +### DaoFacotry를 사용하는 어플리케이션 컨텍스트 +- DaoFactory를 스프링의 빈 팩토리가 사용할 수 있는 본격적인 설정정보로 만들자. + +> @Configuration : 스프링이 빈 팩토리를 위한 오브젝트 설정을 담당하는 클래스라고 인식. +> @Bean : 오브젝트를 만들어주는 메소드 +> ``` java +> @Configuration +> public class DaoFactory { +> @Bean +> public UserDao userDao() { +> return new UserDao(connectionMaker()); +> } +> +> ... +> +> @Bean +> public ConnectionMaker connectionMaker() { +> return new DConenctionMaker(); +> } +> ``` + +### 1.5.2 애플리케이션 컨텍스트의 동작방식 + +- @Configuration 이 붙은 DaoFactory 는 이 애플리케이션 컨테스트를 활용하는 **IoC 설정정보** +- 애플리케이션 컨텍스트는 DaoFactory 클래스를 설정정보로 등록해두고 @Bean이 붙은 메소드의 이름을 가져와 빈 목록을 만든다 +- 클라이언트가 애플리케이션 컨텍스트의 getBean() 메소드를 호출하면 자신의 빈 목록에서 요청한 이름을 찾는다 +- 있다면 빈을 생성하는 메소드를 호출해서 오브젝트를 생성시킨 후 클라이언트에 돌려준다. + + + +### 1.5.3 스프링 IoC 용어 정리 + +### 빈 +- 스프링이 IoC방식으로 관리하는 오브젝트. +- 스프링이 직접 그 생성과 제어를 담당하는 오브젝트만을 빈이라고 부른다. + +### 빈 팩토리 +- 스프링의 IoC를 담당하는 핵심 컨테이너. +- 빈을 등록,생성,조회 그 외에 부가적인 빈을 관리한다. +- 보통은 이 빈 팩토리를 바로 사용하지 않고, 이를 확장한 **어플리케이션 컨텍스트**를 이용한다. + +### 애플리케이션 컨텍스트 +- 빈 팩토리를 확장한 IoC 컨테이너. +- 기본적인 기능은 빈 팩토리와 동일하다, + 스프링이 제공하는 각종 부가 서비스를 추가로 제공. +- BeanFactory를 상속한다. + +### 설정정보/설정 메타정보 +- 애플리케이션 컨텍스트 또는 빈 팩토리가 IoC를 적용하기 위해 사용하는 메타정보를 말한다. + +### 컨테이너 +- IoC 방식으로 빈을 관리한다는 의미에서 애플리케이션 컨텍스트나 빈 팩토리를 컨테이너라고도 한다. + +*** + +## 1.6 싱글톤 레지스트리와 오브젝트 스코프 + +> **오브젝트의 동일성과 동등성** +>> 자바에서 두 개의 오브젝트가 같다? +>> 완전히 같은 동일한 오브젝트 vs 동일한 정보를 담고 있는 오브젝트 +>> 동일성은 == 연산자, 동등성은 equals() 메소드. +> +>두 개의 오브젝트가 동일하다 +> > 사실은 하나의 오브젝트만 존재. 두 개의 오브젝트 레퍼런스 변수를 갖고 있을 뿐. +> +> 두 개의 오브젝트가 동등하다 +> > 두 개의 각기 다른 오브젝트가 메모리상에 존재하는 것, 두 오브젝트의 정보가 동등하다. +> +> 자바 클래스만들 때, 따로 equals() 를 구현하지 않았다면, 최상위 클래스인 Object 클래스에 구현되어있는 equals() 메소드가 사용된다. +> > Object의 equals() 메소드는 두 오브젝트의 동일성을 비교하기 때문에 이때는 동일한 오브젝트여야 동등한 오브젝트로 여겨진다. + +*** +## 1.6.1 싱글톤 레지스트리로서의 애플리케이션 컨텍스트 +- 스프링은 기본적으로 별다른 설정을 하지 않으면 내부에서 생성하는 빈 오브젝트를 모두 **싱글톤** 으로 만든다. + + +## 서버 애플리케이션과 싱글톤 +- 태생적으로 스프링은 엔터프라이즈 시스템을 위해 고안된 기술이기 때문에 서버 환경에서 사용될 때 그 가치가 있다. 실제로 스프링은 대부분 서버환경에서 사용된다. + +이전의 문제점 +- 매번 클라이언트에서 요청이 올 떄마다 각 로직을 담당하는 오브젝트를 새로 만들어서 사용한다고 생각해보자. +- 요청 한번에 5개의 오브젝트가 새로 만들어지고 초당 500개의 요청이 들어오면, 초당 2500개의 새로운 오브젝트가 생성된다. + +### 싱글톤 패턴의 한계 + +자바에서 싱글톤을 구현하는 방법. +- 클래스 밖에서는 오브젝트를 생성하지 못하도록 생성자를 private 로 만든다. +- 생성된 싱글톤 오브젝트를 저장할 수 있는 자신과 같은 타입의 스태틱 필드 정의. +- 스태틱 팩토리 메소드인 getInstance() 를 만들고 이 메소드가 최초로 호출되는 시점에서 한번만 오브젝트를 만들어지게 한다. +- 생성된 오브젝트는 스태틱 필드에 저장된다. +- 한번 오브젝트(싱글톤) 가 만들어지고 난 후에는 getInstance()를 이용해 이미 만들어져 스태틱 필드에 저장해둔 오브젝틀르 넘겨준다. + +>싱글톤 패턴을 적용한 UserDao +>```java +>public class UserDao { +> private static UserDao INSTANCE; +> +> ... +> +> public static synchronized UserDao getInstance() { +> if(INSTANCE == null) INSTANCE = new UserDao(???); +> return INSTANCE; +> } +>} +>``` + +### 싱글톤 패턴의 문제점 +- private 생성자를 갖고 있기 떄문에 상속불가. + - 객체지향의 장점인 상속과 이를 이용한 다형성을 적용할 수 없다. +- 싱글톤은 테스트하기가 힘들다. +- 서버환경에서는 싱글톤이 하나만 만들어지는 것을 보장하지 못한다. +- 싱글톤의 사용은 전역 상태를 만들수 있기 때문에 바람직하지 못하다. + +# 싱글톤 레지스트리 +- 스프링은 직접 싱글톤 형태의 오브젝트를 만들고 관리하는 기능을 제공한다. 이를 싱글톤 레지스트리 라고 한다. +- 스프링 컨테이너는 싱글톤을 생성하고, 관리하고, 공급하는 싱글톤 관리 컨테이너이기도 하다. + +## 싱글톤 레지스트리 장점 +- 스태틱 메소드와 Private 생성자를 사용해야 하는 비정상적인 클래스가 아니라 평범한 자바클래스를 싱글톤으로 활용하게 해준다. +- 평범한 자바 클래스라도 IoC 방식의 컨테이너를 사용해서 생성과 관계설정, 사용 등에 대한 제어권을 컨테이너에게 넘기면 손쉽게 싱글톤 방식으로 만들어져 관리할 수 있게 한다. +- **싱글톤 패턴과 달리 스프링이 지지하는 객체지향적인 설계 방식과 원칙, 디자인 패턴 등을 적용하는데 아무런 제약이 없다**. + +*** + +### 1.6.2 싱글톤과 오브젝트의 상태 + +- 싱글톤은 멀티스레드 환경이라면 여러 스레드가 동시에 접근해서 사용할 수 있다. 따라서 상태관리 중요!! +>기본적으로 싱글톤이 멀티스레드 환경에서 서비스 형태의 오브젝트로 사용되는 경우에는 상태정보를 내부에 갖고 있지 않은 **무상태 stateless** 방식으로 만들어져야 한다. +> > 이유 +> > 다중 사용자의 요청을 한꺼번에 처리하는 스레드들이 동시에 싱글톤 오브젝트의 인스턴스 변수를 수정하는 것은 매우위험하다. 저장할 공간이 하나뿐이니 서로 값을 덮어쓰고 자신이 저장하지 않은 값을 읽어올 수 있기 때문이다. +>- 따라서 싱글톤은 기본적으로 인스턴스 필드 값을 변경하고 유지하는 **상태유지 stateful** 방식으로 만들지 않는다. + + +*** + +## 1.7 의존관계 주입(DI) + +### 1.7.1 제어의 역전과 의존관계 주입 + +- 객체를 생성하고 관계를 맺어주는 등의 작업을 담당하는 기능을 일반화한것이 스프링의 IoC컨테이너이다. +- 스프링의 IoC 기능의 대표적인 동작원리는 주로 의존관계주입이라 불린다. + + +### 1.7.2 런타임 의존관계 설정 + +### 의존관계 + +- A가 B에 의존하고 있다. -> B가 변하면 그것이 A에 영향을 미친다. 반대로 B는 A의 영향을 받지 않는다. +> 의존관계 주입 세가지 조건 +1. 클래스 모델이나 코드에는 런타임 시점의 의존관계가 드러나지 않는다. 그러기 위해서는 인터페이스에만 의존하고 있어야한다. +2. 런타임 시점의 의존관계는 컨테이너나 팩토리 같은 제3의 존재가 결정한다. +3. 의존관계는 사용할 오브젝트에 대한 레퍼런스를 외부에서 제공해줌으로써 만들어진다. + + +의존관계 주입의 핵심은 설계 시점에는 알지 못했던 두 오브젝트의 관계를 맺도록 도와주는 제3의 존재. + +*** + +### 1.7.4 의존관계 주입의 응용 + +### 기능 구현의 교환 + +> 상황 : 로컬 개발중에 로컬 DB에 연결하여 작업중이여서 LocalDBConnectionMaker 라는 클래스를 만들고 사용하다가 다시 서버에 배치하는 시점에는 ProductionDBConnectionMaker 라는 클래스로 변경해줘야한다. + +- DI 방식을 적용해서 만들어보자. +- 모든 DAO는 생성 시점에 ConnectionMaker 타입의 오브젝트를 컨테이너로부터 제공받는다. +- 단지 DI의 설정정보에 해당하는 DaoFactory 만 다르게 만들어 두면 나머지 코드에는 전혀 손대지 않고 개발 시와 운영시에 각각 다른 런타임 오브젝트에 의존관계를 갖게 해줘서 문제를 해결할 수 있다. + +> 개발용 ConnectionMaker 생성 코드 +> ```java +> @Bean +> public ConnectionMakwer connectionMaker() { +> return new LocalDBConnectionMaker(); +> } +>``` +> 운영용 ConnectionMaker 생성 코드 +> ```java +> @Bean +> public ConnectionMaker connectionMaker() { +> return new ProductionDBConnectionMaker(); +> } +>``` + +### 부가기능 추가 + +- DB연결횟수를 카운팅 하고싶다! + + +*** + + +### 1.7.5 메소드를 이용한 의존관계 주입 + +- 이전까지는 생성자를 통해 의존관계 주입을 하였다. +- 생성자가 아닌 일반 메소드를 사용할 수도 있을 뿐만 아니라, 생성자를 사용하는 방법보다 더 자주 사용된다. + + +*** + +## 정리 + +- 책임이 다른 코드 분리해서 두 개의 클래스로 만들었다 (관심사의 분리 , 리팩토링) +- 그 중에서 바뀔수 있는 쪽의 클래스는 인터페이스를 구현하도록 하고, 다른 클래스에서 인터페이스를 통해서만 접근하도록 만들었다. +- 자신의 책임 자체가 변경되는 경우 외에는 불필요한 변화가 발생하지 않도록 막아주고, 자신이 사용하는 외부 오브젝트의 기능은 자유롭게 확장하거나 변경할 수 있게 만들었다. (개방 폐쇄 원칙) +- 결국 한 쪽의 기능 변화가 다른 쪽의 변경을 요구하지 않아도 되게 했고, 자신의 책임과 관심사에만 순수하게 집중하도록. (낮은 결합도와 높은 응집도) +- 오브젝트 팩토리의 기능을 일반화한 IoC 컨테이너로 넘겨서 오브젝트가 자신이 사용할 대상의 생성이나 선택에 관한 책임으로부터 자유롭게 만들어줬다. +- 전통적인 싱글톤 패턴 구현 방식의 단점 파악, 싱글톤 레지스트리. +- 구체적인 의존 오브젝트를 DI 컨테이너의 도움으로 주입받아, 다이내믹한 의존관계를 갖게 해주는 IoC의 특별한 케이스 +- 의존 오브젝트를 주입할 때 생성자를 이용한 방법과 수정자 메소드를 이용하는 방법을 알아봄.