CH2-1. 생성자 대신 static factory method 고려하기 Effective Java 3rd

CH2

- object 만들고 없애기.

1. 생성자 대신 static factory method 고려하기.


public static Boolean valueOf(boolean b) {
return b ? Boolean.TRUE : Boolean.FALSE;
}



About Constructor

http://olc.kr/mypage/course_list.jsp

Java Advanced Programming 2

Reflection이란?
실행시간에 메모리 구조를 활용하여 동적 제어를 하는 프로그래밍 할 때 사용.

장점 : 
무한한 확장성
동적 제어가 가능한 프로그래밍
객체들 간의 의존성이 없는 프로그래밍 
단점 
performance overhead 
security 제약 - 익셉션, 에러 (자바로는 바이러스를 만들 수 없다..) 
(oop의 관점 - 복잡성 증가는 어쩔수없음 얼마나 유연한 구조를 가지는가!)

동적로딩 - class.forName
클래스를 메모리상에 동적으로 로딩하는 방식
필요한 경우에 newInstance같은걸로 객체 생성 가능. 

https://docs.oracle.com/javase/7/docs/api/
Class라는 클래스로 무엇을 알 수 있을까?
java.lang.Class
public final class Class<T> 파이널이다 그래서 마음대로 오버라이딩이 안됨. 
생성자 정보
getDeclaredConstructor(Class<?>... parameterTypes) 선언되어있는 생성자 찾음 오버로딩을 위해 파라미터를 저렇게 받음. 
void도 클래스다. 
필드(property) 
메소드
상속관계 
subclass, assubclass
인터페이스
Annotation
	

//에러남 
public class CreateTest {
public static  void main(String args) /{
Class clazz = class.forName("testObj");
Object obj = clz.newInstance();
System.out.println(obj);
}
}

public class TestObj {
private String value;

public TestObj(String value) {
super();
this.value = value;
}

}


///에러안남. 인자 안받는거 넣었을 뿐인데?
public class CreateTest {
public static  void main(String args) /{
Class clazz = class.forName("testObj");
Object obj = clz.newInstance();
System.out.println(obj);
}
}

public class TestObj {
private String value;

   public TestObj(String value) {
super();
}

public TestObj(String value) {
super();
this.value = value;
}

}

그럼 생성자의 정체가 뭐냐?? 
어셈블리 코드를 보아요...
javap -verbose TestObj.class


디폴트 생성자가 필요한 이우 
파라미터가 잇으면 super()가 묵살된다. 
오브젝트를 만들 수 없다! 
class.forName은 바로 디폴트 생성자를 부르는데 기본생성자가 없어져 버리면 

생성자 : 객체를 만드는 방법을 제한한다. 

그런경우에 constructor를 뽑아내야한다. 
프레임워크에서 컨스트럭터를 넣어주는 이유는 컨스트럭터가 있으면 일반적으로 개체를 만들 수 없으니까! 


Constructor con = clz.getDeclaredConstructor(String.class);
this도 스테틱 variable이다. 
모든 객체는 어떤 클래스에 속하는지 메타 데이터를 가진다. static르로 super에 저장.

objectType -> generic 
Object obj = con.newInstance("AAA");

결론
사용자 저으이 생성자가 있는 경우 
classforname으로 init할수없다. 객체의 lifecycle이용해서 만들 수 없다 
그래서 constructor를 구해서 거기서 instance를 구해야 한다.






1.2.3 사용 시나리오 spring reference


2.3 Usage scenarios

앞에서 설명한 빌딩블락은 리소스가 제한된 장비에서 돌아가는 임베디드 응용 프로그램부터 스프링의 트랜젝션 관리 기능과 웹 프레임워크 통합을 사용하는 완전한 엔터프라이즈 응용 프로그램에 이르기까지 다양한 시나리오에서 스프링을 논리적인 선택으로 만듭니다.  

스프링의 선언적 트랜젝션 관리 기능은 EJB 컨테이너로 관리하는 트랜젝션들을 사용하는 것 처럼 웹 어플리케이션을 완전히 트랜젝션적으로 만듭니다. 
모든 당신의 커스텀 비지니스 로직은 간단한 POJO로 구현되고 스프링 IOC 컨테이너에 관리된다.  추가 서비스에는 배리데이션 규칙을 실행할 위치를 선택 할 수 있는 웹계층과 독립적인 유효성 검사 및 이메일 전송 지원이 포함됩니다. 스프링 ORM 지원은 JPA, 하이버네이트, JDO들과의 통합되었다. 
즉, 하이버 네이트를 사용할 때 당신은 존재하는 매핑 파일과 표준 하이퍼베이트 session factory 설정을 지속할 수 있다. 
폼 컨트롤러는 웹 모델과 도메인 모델을 완벽하게 통합하여 HTTP 매개변수를 도메인 모델의 값으로 변환하는 ActionForms 또는 기타 클래스의 필요성을 제거합니다.
때때로 당신이 완전히 다른 프레임워크로 바꾸는 것이 어려울 수 있다.  스프링 프레임워크는 당신이 스프링 안에서 사용하는것을 모든 일을 하도록 강제하지 않는다. 스프링은 all or nothing 솔루션이 아니다.  
Struts, Tapestry, JSP등 다른 UI프레임워크로 만들어진 front-end가 스프링 트랜젝션 기능이 사용하는 스프링 기반의 미들티어에 통합될 수 있다. 
어플리케이션 컨텍스트를 사용하여 비즈니스 로직을 연결하고, 웹 어플리케이션 컨텍스트를 사용하여 당신의 웹 레이어에 통합 하기만 하면 됩니다. 

웹 서비스를 통하여 존재하는 코드에 접근해야 할 때, 스프링 Hessian-, Burlap-, Rmi-, JaxRpcProxyFactory클래스를 이용할 수 있습니다. 
존재하는 어플리케이션에 원격으로 접근하는 것은 어렵지 않습니다.

스프링 프레임워크는 access와 EnterPrise JavaBean, 존재하는 POJO의 재사용을 허용, 선언적 보안이 필요한 확장성 있고 안전한 웹 어플리케이션을 사용하는 무상태 세션 빈을 감싸기 위해 접근과 추상화 계층을 제공한다.

2.3.1 Dependency Management and Naming Conventions

의존성 관리와 의존성 주입은 다르다. (의존성 주임과 같은 이런 좋은 스프링의 기능들을 사용하기 위해 모든 라이브러리가 필요하고, 런터임시에 혹은 가능하다면 컴파일 시에 클래스 경로에 올로와 있어야 한다. 이런 의존성들은 주입되는 가상 컴포넌트가 아닌 파일시스템상의 물리적 자원이다. 
이런 의존성 관리 프로세스는 그런 자원들의 배치, 저장, 그리고 클래스 경로에 추가하는 과정들을 포함한다.  의존성들은 직접적이 될수도 간접적이 될수도 있다. (직접적 : 런터임에 의존, 간접적 :  commons-pool 기반의 common-cbcp에 의존).  간접적 의존성은 transitive로 알려져있다 그리고 이런 의존성들은 구별하고 관리하는게 힘들다. 

스프링을 쓸 계획이라면, 필요한 스플이의 일부를 포함하는 jar라이브러리의 복사본이 필요하다. 스프링은 의존성이 최대한 분리되도록 모듈이 패키징 되어 있어 이 작업을 쉽게 할 수 있다. 그래서 예를들어 스프링 웹 어플리케이션을 작성할 것이 아니라면 스프링 웹 모듈은 필요가 없다.
이 가이드의 스프링 라이브러리 모듈을 참조하기 위해 spring-*, spring-*.jar와 같은 ?짧은 작명 컨벤션을 사용한다.  (* 이 spring-core나 spring-webmvc같은 해당 모듈의 짧은 이름이 들어간다)

보통 결과물은 아래의 위치에 배포한다.

  - 메이븐 센트럴(Maven Central). 메이븐 센트럴은 메이븐의 기본 저장소이므로 사용하기 위해서 특별한 설정을 할 필요는 없다. 스프링이 의존하는 공통 라이브러리 중 다수는 메이슨 센트럴에서 이용할 수 있고 스프링 커뮤니티의 많은 부분은 의존성 관리에 메이븐을 사용하므로 편리하다. 메이븐 센트럴의 jar 파일명은 spring-*-<version>.jar의 형식을 따르고 메이븐 groupId는 org.springframework이다.
  - 특별히 스프링을 위해 호스팅된 공용 메이븐 저장소. 최종 GA릴리즈 외에도 이 저장소는 개발 스냅샷 및 마일스톤을 제공한다. jar파일 이름들은 메이븐 센트럴과 동일하다, 그래서 메이븐 센트럴에 배포된 스프링의 다른 라이브러리와 함께 스프링 개발 버전을 사용할 때 용이한 곳이다.
이 저장소는 또한 쉡게 다운로드 할 수 있또록 함게 번들로 묶인 모든 모든 스프링의 jar를 포함하는 번들을 포함합니다. 

그래서 어떻게 의존성을 관리할 것인지를 먼저 결정해야 한다. 대부분은 메이븐이나 아이비같은 자동화된 시스템을 사용한다. 하지만 수동으로 모든 jar를 다운받아서 관리할 수도 있다.

아래 리스트는 sprint artifacts이다. 각 모듈별설명을 더 자세히 보고싶은 2.2섹션을 보라. 

Spring Dependices and Depending on Spring 

스프링이 큰 범위의 엔터프라이즈 및 외부 도구에 대한 통합 및 지원을 제공하지만, 강제적 종속성을 의도적으로 최소한으로 유지합니다.
간단한 유즈케이스를 위한 스프링을 사용을 위해 많은 양의 jar라이브러리들을 다운받고 위치시킬 필요가 없습니다. (심지어 자동으로 되더라도요)
기본적인 의존성 주입을 위해 필요한 외부 dependency는 단 하나뿐이고 그것조차 로깅을 위한 것입니다. ( 아래에 더 자세한 로깅 옵션에 대한 설명이 있습니다.)

다음은 스프링에 의존하는 애플리케이션을 설정하는데 필요한 기본적인 과정을 설명할 차례이다. 먼저 메이븐으로 그리고 그래들로 마지막으로 아이비를 사용한다. 모든 경우에 명확한 것이 없다면, 의존성 관리 시스템의 문서를 참고하거나 예제코드를 보아라. 스프링은 빌드시에 의존성을 관리하기 위해서 그래들을 사용한다 그리고 우리 샘플들은 대부분 그래들이나 메이븐을 사용한다. 

Maven Dependency Management

만약 니가 의존성 관리를 위해 메이븐을 이용한다면 너는 로깅 dependency도 명시적으로 제공할 필요 없다.  예를들어 애플리케이션 컨택스트를 만들고 의존성 주입을 애플리케이션을 구성하는데 사용하고자 할 때 너의 메이븐 dependencise는 아래와 같을것이다. 


<dependencies>    <dependency>        <groupId>org.springframework</groupId>        <artifactId>spring-context</artifactId>        <version>4.3.10.RELEASE</version>        <scope>runtime</scope>    </dependency></dependencies>
기본 종속성 삽입 사용시 spring api에 대해 컴파일 할 필요가 없는 경우 범위를 런타입으로 선언 할 수 있다.

위의 예시는 Maven Central Repository에서 작동한다. 스프링 메이븐 저장소를 이용하기 위해 repository locaiton을 메이븐 설정에 지정해야 한다. 
<repositories>    <repository>        <id>io.spring.repo.maven.release</id>        <url>http://repo.spring.io/release/</url>        <snapshots><enabled>false</enabled></snapshots>    </repository></repositories>

For milestones:

<repositories>    <repository>        <id>io.spring.repo.maven.milestone</id>        <url>http://repo.spring.io/milestone/</url>        <snapshots><enabled>false</enabled></snapshots>    </repository></repositories>

And for snapshots:

<repositories>    <repository>        <id>io.spring.repo.maven.snapshot</id>        <url>http://repo.spring.io/snapshot/</url>        <snapshots><enabled>true</enabled></snapshots>    </repository></repositories>


Maven "Bills Of Materials" Dependency

메이븐 쓰다보면 spring jar 파일이 다른버전이 우연히 섞일 수 있다. 예를들어 외부 라이브러리를 쓸 때 아니면 다른 스프링 프로젝트가 이전 배포 버전에 대해 의존성을 가져올 수 있습니다. 만약 니가 적접적으로 의존성을 명시하는 것을 까먹었다면 모든 종류의 예상치 못한 문제가 발생할 수 있습니다. 

그런 문제를 해결하기 위해 메이븐은 Bills Of Materials(BOM) 의존성이란느 개념을 지원합니다.  spring framework-bom 를 dependencyManagement 섹션에 넣어서 스프링 의존성이 같은 버전임을 확신할 수 있게 됩니다. 

<dependencyManagement>    <dependencies>        <dependency>            <groupId>org.springframework</groupId>            <artifactId>spring-framework-bom</artifactId>            <version>4.3.10.RELEASE</version>            <type>pom</type>            <scope>import</scope>        </dependency>    </dependencies></dependencyManagement>

BOMs를 넣음으로써 생기는 이점은 더이상 버전이라는 속성이 필요가 없어집니다. 

<dependencies>    <dependency>        <groupId>org.springframework</groupId>        <artifactId>spring-context</artifactId>    </dependency>    <dependency>        <groupId>org.springframework</groupId>        <artifactId>spring-web</artifactId>    </dependency><dependencies>


Gradle Dependency Management


스프링 저장소를 그래들 시스템으로 이용하고자 한다면 적절한 URL을 repositories 구역에 넣어야 합니다. 

repositories {    mavenCentral()    // and optionally...    maven { url "http://repo.spring.io/release" }}

repositories의 url을 /release, /milestone or /snapshot 등 적절하게 바꿀 수 있습니다. 

저장소가 한번 정해지면 그래들의 방식으로 의존성을 선언 할 수 있습니다. 

dependencies {    compile("org.springframework:spring-context:4.3.10.RELEASE")    testCompile("org.springframework:spring-test:4.3.10.RELEASE")}






1장 스프링 프레임워크 소개 #1 spring reference

나도 해보자 스프링 레퍼런스 읽고 번역하기!

참고 ) https://blog.outsider.ne.kr/729
https://docs.spring.io/spring/docs/current/spring-framework-reference/htmlsingle/#spring-introduction

한글 번역해주신분은 3.1버전이고 지금은 4.3.9버전이니까 두개 차이를 비교하면서 번역해보기로하자
약 700페이지라고 하니까 일년 근무일수 약 250일로 잡으면 하루에 3페이지씩 번역하면 1년안에 되지않을까 합니다. 
음.. 아니야.. 마음편하게 꼴리는대로하자. 


Part 1. Spring Framework 개요. 

스프링 프레임워크는 엔터프라이즈급 애플리케이션을 만들기 위한 경량 솔루션이며, one-stop-shop이다. 
하지만 스프링은 다른 나머지 부분 없이, 니가 필요한 부분만 이용할 수 있도록 모듈화 되어있다. 
너는 아무 웹 프레임워크 위에 IoC 컨테이너를 이용할 수 있다 또한 하이버네이트통합 코드JDBC추상화 계층만 이용할 수 도 있다. 
스프링 프레임워크는 RMI나 웹서비스로 로직에 원격접속하는 선언적 트랜젝션 관리와 데이터를 유지하는 다양한 옵션을 제공한다. 스프링은 너의 소프트웨어에 full-featured MVC를 제공하고 투명하게 aop를 합칠수있다.

스프링은 침투적이지 않게 디자인 되어있다 (도메인 로직 코드가 일반적으로 프레임워크에 의존적이지 않다) 
DAO와 같은 통합 레이어에서 데이터 접근 기술과 스프링 라이브러리에 대한 의존성이 존재하지만, 하지만 이런 의존성이 너의 다른 코드들과 독립적으로 만들기는 쉽다. 

이 문서는 스프링 프레임워크의 feature들의 레퍼런스 가이드이다. 이 문서에 대한 질문이나 코멘트가 있으면 메일링 리스트로 보내라. 프레임워크 자체에 질문이 있으면 스택오버플로우로 물어봐라.(see https://spring.io/questions).


1. 스프링으로 시작하기.

이 레퍼런스 가이드는 스프링 프레임워크에 대한 자세한 정보를 제공한다. 이것은 모든 features들의 포괄적인 문서를 제공할 뿐만 아니라 스프링이 가지고 있는 개념을 이해하는데 배경지식을 제공한다. 

당신이 만약 지금 스프링을 시작한다면, 너는 스프링 부트기반 애플리케이션을 만들어서 스프링 프레임워크를 이용 할 수 있다. 스프링 부트는 스프링 기반의 애플리케이션을 만드는 빠른 방법이다. 부트는 스프링 프레임워크를 기반으로 convention을 따라 가능한 빠르게 작동시킬 수있도록 디자인 되어있습니다. 

시작하기 가이드, RESTful webservice 시작하기 가이드를 따라하거나 기본 프로젝트를 만드는데 start.spring.io 페이지를 이용할 수 있습니다. 이런 가이드들은 만들기 쉽고, task에 집중되어있으며 대부분이 스프링 부트를 기반으로 하고있습니다. 
또한 가이드는 당신이 특정한 문제를 풀려고 할 때 스프링 포트폴리오의 다른프로젝트들로 커버할수있다.

2. 스프링 프레임워크 소개. 

스프링은 자바 애플리케이션을 개발하는데 포괄적인 기반을 제공하는 자바 플랫폼이다. 당신이 당신의 애플리케이션에 집중할 수 있도록 스플이은 기반을 다룬다. 

스프링은 가능하게 한다 너가 어플리케이션을 만들 수 있게 포조로부터 그리고 적용한따 전체 서비스가 포조와 칩투되어있지않은 
스프링은 plan old Java object(POJOs)로 애플리 케이션을 만들 수 있고, 또 엔터프라이즈 서비스로 비 침투적으로 POJOs에 적용할 수 있다. 이 능력은 자바 SE 프로그래밍 모델에 적용되고 java ee에 전체 혹은 부분적으로 적용된다. 

애플리케이션 개발자로서 당신이 어떻게 스프링 플랫폼의 이익을 볼 수 있는지 예제이다.
  - 트랜젝션API를 이용하지 않고도 데이터베이스 트랜젝션에서 자바 메소드를 실행하도록 만든다.
  - Servlet API를 이용하지 않고 로컬자바 메소드를 HTTP 엔드포인트를 만들 수 있다. 
  - JMS API를 이용하지 않고 로컬자바 메소드를 메세지 핸들러를 만들수 있다.
  - JMX API를 이용하지 않고 로컬 자바 메소드를 관리 작업으로 만든다. 


2.1 의존성 주입(Dependency Injection) 과 

제어의 역전( Inversion of Control  )

 자바 애플리케이션은 -- 제한적은 애플릿으로 부터 n티어 서버사이드 엔터프라이즈 애플리케이션까지 포함하는 의미이다 -- 보통 애플리캐이션에 적합한 객체로 이루어저 있다. 그래서 애플리케이션의 객체는 서로간의 의존성을 가진다. 

비록 자바 플랫폼이 애플리케이션 개발에 풍부한 기능을 제공하지만, 전체를 논리적으로 기초를 구상하는 방법이 부족하여 이런 남은 작업들은 개발자와 아키텍쳐가 해야한다. 사실 당신은 다양한 클래스와 객체를 조합하여 애플리 케이션을 만드는데, Factory, Abstract Factory, Builder, Decorator and Service Locator와 같은 디자인 패턴을 사용할 수 있다. 하지만, 이런 패턴들은 베스트 프랙티스에 이름을 주어 어떤 패턴이 어떤일을 하고 어디에 적용해야하는지 어떤 문제에 대한 것인지 설명한 것 뿐이다. 패턴들은 당신이 애플리케이션에서 구현해야 하는 베스트 프랙티스를 형식화 한 것이다. 

스프링의 제어의 역전(IoC) 컴포넌트는 서로다른 컴포넌트를 완전히 작동될 준비가 된 애플리케이션으로 조립시키는 형식화된 방법을 제공하여이런 문제를 해결합니다. 
스프링 프레임워크는 자신의 애플리케이션으로 통합할 수 있는 퍼스트 클래스 객체를 형식화된 디자인 패턴으로 만들었다.
수많은 조직과 협회는 신뢰할 수 있고 유지보수 가능한 어플리케이션을 만들려고 이 방법으로 스프링 프레임워크를 사용한다.


배경

“제어의 어떤 관점이 역전되었는가?” 마틴 파울러(Martin Fowler)는 2004년 자신의 사이트에서 제어의 역전(IoC)에 대한 의견을 말했다. 파울러는 원리가 더 명확하게 드러나도록 이름을 의존성 주입(Dependency Injection)으로 바꾸어야 한다고 제한했다.
IoC와 DI를 더 알고 싶다면 http://martinfowler.com/articles/injection.html에 올라온 파울러의 글을 참고해라.


1.2 모듈

스프링 프레임워크는 약 20개의 모듈로 이루어져 있다. 이런 모듈들은  아래 그림과 같이  Core Container, Data Access/Integration, Web, AOP (Aspect Oriented Programming), Instrumentation, Messaging, and Test으로 이루어져 있다.



다음 섹션은 각 기능의 사용가능한 모듈과 해당 이슈 이름 및 해당 항목에 대해 설명합니다.
이슈 이름은 의존성 관리 툴로서 사용되는 이슈의  ID와 관련있습니다. 


2.2.1 Core Container

코어 컨테이너는 spring-core, spring-beans, spring-context, spring-context-support, spring-expression모듈로 이루어져 있습니다.

스프링 코어와 스프링 빈 모듈은  IoC와 DI와 같은 프레임워크의 기반을 제공한다. BeanFactory는 팩토리 패턴을 높은 수준으로 구현했다.  프로그래밍 방식의 싱글톤을 구현할 필요가 없고, 구성을 분리할 수 있게하고, 프로그램의 로직으로 부터 의존성에 대한 설정과 명세를 분리할 수 있다. 

Context 모듈은 코어와 빈 모듈에서 제공하는 단단한 기반 위에 구성된다. 그말은 JNDI레지스트리와 유사하게 프레임워크 스타일 방식으로 오브젝트에 접근한다. 컨텍스트 모듈은 빈즈 모듈의 특징을 상속받는다 그리고 국제화 이벤트 전파, 리소스 로딩, 서블린 컨테이너 컨텍스트의 투명한 생성에 대한 지원을 추가한다. EJB, JMX, basic remoting과 같은 Java EE의 특징을 지원한다. 
Application Context  인터페이스는 컨텍스트 모듈에서 중요하다. spring-context-support 가 
(캐싱, 메일링, 스케줄링, 템플릿 엔진)을 이용하기 위한 스프링 애플리케이션 컨텍스트에 common third-party libray에 통합하기 위한 지원을 제공한다.
 caching (EhCache, Guava, JCache), mailing (JavaMail), scheduling (CommonJ, Quartz) and template engines (FreeMarker, JasperReports, Velocity).


spring expression 모듈은 쿼리와 런타임시 객체 그래프를 조회하고 조작하는 강력한 표현 언어를 제공한다. 
JSP 2.1스펙에 정의된 Undefined Expression Language의 확장이다. 
property value를 설정하고 가지고 오는 기능과  속성 할당, 메서드 호출, 배열과 컬렉션과 인덱서의 컨텍스트 접근, 논리적/산술적 오퍼레이터, 이름있는 변수, 스프링의 IoC 컨테이너에서 이름으로 객체를 획득하는 기능을 지원한다.
일반적인 리스트 집합뿐만 아니라 리스트의 투영과 선택도 지원한다. 



2.2.2 AOP 와 Instrumemtation

스프링의 AOP 모듈은 AOP Alliance를 따르는 관점지향 프로그래밍의 구현체다. 예를 들어 기능적으로 분리되어야 하는 코드를 깔끔하게 분리하는 메서드-인터셉터와 포인트컷을 정의할 수 있다. 소스레벨의 메타데이터 기능을 사용하면 .NET 어트리뷰트와 유사한 방법으로 행동에 관한 정보를 코드로 구현할 수 있다.

spring-aspects 모듈은 AspcetJ와의 통합을 제공합니다. 

spring instrument모듈은 인스트루멘테이션을 지원하는 클리새와 특정 애플리케이션 서버에서 사용되는 클래스로더  구현체를 제공한다. 
spring instrument tomcat모듈은 스프링 톰캣 instrumetation agent 에 들어있다. 

2.2.3 Messaging

스프링 4 버전엔 메세지 기반 애플리케이션의 기초인 Message, MessageChannel, MessageHandler같은  스프링 Integration project로부터 key를 추상화하는 spring message모듈이 있다. 
메세지 모듈은 프로그래밍 모듈을 기반으로한 스프링MVC어노테이션 처럼 메세지를 메소드에 매핑시킨는 어노테이션의 세트를 포함한다.

2.2.4 Data Access/Integration

Data Access/Integration 계층은 JDBC,ORM,OXM,JSM, 트랜젝션 모듈로 구성된다. 
Spring jdbc모듈은 jdbc추상화 계층을 제공한하여 지루한 jdbc코딩과 파싱 database-vendor에서 정의한 에러코드들을 제거한다. 
spring tx모듈은 특별한 인터페이스와 모든 너의 POJO를 관리하는 클래스를 이용프로그래밍적, 선언트랜젝션 관리를 제공한다.
spring -orm 모듈은 JPA, JDO, Hibernate와 같은 유명한 객체 - 관계형 매핑 API를 위한 통합 레이어를 제공한다. 
spring-orm 모듈을 이용하여 당신은 앞에서 말했던 간단한 선언적 트랜젝션 관리 기능과 같은 스프링이 제공하는 이런 모든 객체/관계형 매핑 프레임워크를 이용할 수 있다. 
spring-oxm 모듈은 JAXB, Castor, XMLBeans, JiBX,  XStream과 같은 객체/xml매핑하는 추상 레이어를 제공한다.
spring -jms모듈은 메세지를 만들고 소비하는 기능을 가진다.  스프링 4.1 부터 spring-messaging 모듈로 제공된다. 

2.2.5. Web

웹 레이어는 spring-web, spring-webmvc, spring-websocket, spring-webmvc-portlet 모듈로 구성된다. 
spring-web모듈은 다중 파일 업로드, 서블릿 리스너와 web-oriented application context를 이용한 Ioc Container의 초기화 기본적인 웹 기반 통합 기능을 제공한다.
spring-webmvc모듈은 (web-servlet모듈) 웹 앱을 위한 rest와 mvc를 포함한다.
spring mvc framework에는 도메인모델 코드와 웹 폼 그리고  스프링 프레임워크의 모든 다른 기능들이 깔끔하게 분리되어있다. 

spring web-mvc-portlet모듈은 포틀릿 환경에서 사용되는 mvc구현과 웹  서블릿 모듈 기능의 미러 기능을 제공한다. 

2.2.6 TEST

spring test 모듈은 JUnit 이나 TESTNG 등의 스프링 컴포넌트로 단위 테스트와 통합 테스트를 지원한다. Spring Application Context와 이런 컨텍스츠의 캐싱의 안정된 로딩을 제공한다. 목 오브젝트를 제공하여 독립적으로 테스트가 가능하게 해준다. 


===== 2-1 Super Type Token ===== java-spring 토비 강의

===== 2-1 Super Type Token =====
Generics 
// gafter.blogspot.kr/2006/12/super-type-tokens.html


<code>
public class TypeToken {
static Object create() {
return new Object();
}

public static void main(String[] args) {
Object o = create();
System.out.println(o.getClass());
}
}


public class TypeToken {
static <T> T create(Class<T> clazz) throws Exception {
//캐시스팅 없이 되는 안전한 코드가 된다 . (type eraser)
return clazz.newInstance();
}

public static void main(String[] args) throws Exception {
//Integer o = create(Integer.class);
//에러 남 Integet 는 디폴트 생성자가 없기 때문이다. (System.out.println(new Integer()) 가 안됨 )
Object o = create(String.class);
System.out.println(o.getClass());
}
}


public class TypeToken {
static class Generic<T> {
T value;
void set(T t) {}
T get() { return null; }
}

public static void main(String[] args) throws Exception {
Generic<String> s = new Generic<String>();
s.value = "String";
// type eraser 타입 파라미터를 파라미터라이즈드 타입 Generic 런타임시에 삭제되어 오브젝트 타입이 된다. 그래서 실제 코드 안에 타입 캐스팅을 넣어줌. 
//ex) s.value = (String)"String";

Generic<Integr> i = new Generic<Integer>();
i.value = 1;
i.set(10);
}
}
</code>

타입 안정성 있는 맵
<code>
public class TypeToken {
static class TypesafeMap {
Map<Class<?>, Object> map = new HashMap<>();

<T> void put(Class<T> clazz, T value) {
map.put(clazz, value);
}

<T> T get(Class<T> clazz) {
//return (T) map.get(clazz)) 도 되지만 타입캐스팅을 하기 때문에 좋은 코득 ㅏ아니다 위험! 
return clazz.cast(map.get(clazz));
}
}

//이렇게 타입정보를 값으로 넘기는 것 : type token

public static void main(String[] args) throws Exception {
TypesafeMap m = new TypesafeMap();
m.put(Integer.class, 1);
m.put(String.class, "String");
m.put(List.class, Arrays.asList(1,2,3));

System.out.println(m.get(Integer.class));
System.out.println(m.get(String.class));
System.out.println(m.get(List.class));

}
}
</code>

Neal Gafter 님의 블로그 좋음. 

자바가 처음에는 제네릭이 없었다. 
List<String> 
컴파일 되어 바이트 코드로 만든느 방법 .
1. eraser : 자기 정보를 다 날리고 Object로 바꿔버림. 
장점 : 자바 1.4 때까지 있던 라이브러리와 코드를 그대로 사용 가능 .(호환)
(JAVA) JAVA 5 이전의 개발이 많았다. 
2. refication (refiable type으로 만듬 ) : 구체화 하는 것. 
(c#) : 이 때 만들어진지 얼마 안되어 호환 무시! 


<code>
public class SuperTypeToken {
static class Sup<T> {
T value;
}

public static void main(String[] args) throws Exception {
Sup<String> s = new Sup<>();
System.out.println(s.getClass().getDeclaredFiled("value").getType());
//eraser방식이기 때문에 다 사라져서 String이 아닌 Object가 된다. 
}
}
</code>


<code>
public class SuperTypeToken {
static class Sup<T> {
T value;
}

static class Sub extends Sup<String> {

}

public static void main(String[] args) throws Exception {
Sup s = new Sup();
//클래스 이름만 쓴건 타입 .Object
Type t = b.getClass.getGenericSuperClass();
// Sup<String> 클래스가 들어있는 타입. 
ParameterizedType ptype = (ParameterizedType)t;
System.out.println(ptype.getActualTypeArgument()[0]);
}
}
</code>
  - 클래스의 인스턴스를 만들면서 넣어준 클래스는 호환성 문제때문에 삭제시킨다. 
  - 새로운 타입을 정의하면서 수퍼 클래스를 generic class(타입 파라미터를 가진 ) 으로 지정하면 이 정보는 reflection을 통하여 지정되도록 바이트코드에 남아있다. 
  - 이 때 Sub<String>뿐만 아니라 Sup<List<String>>같이 중첩된 타입 정보도 다 가지고 온다. 


로컬 클래스 : 클래스의 스코프를 로컬로 지정  메소드 안에서만 한번 사용한다. (이름 생략해도 되 생략하면 : annonymous class)
Nested static class == INNER class? 

<code>
public class SuperTypeToken {
static class Sup<T> {
T value;
}


public static void main(String[] args) throws Exception {
//Local Class
class Sub extends Sup<List<String>> { }
//annomymous class
Sup b = new Sub<List<String>>(){};
//inline
Type t = (new Sub<List<String>>() {}).getClass.getGenericSuperClass();


Sup s = new Sup();
Type t = b.getClass.getGenericSuperClass();
ParameterizedType ptype = (ParameterizedType)t;
System.out.println(ptype.getActualTypeArgument()[0]);
}
}
</code>

Spring 
ParameterizedTypeReference가 있다. 
<code>
public class SpringTypeReference {
public static void main (String[] args) {
//spring 3.2 이상 .
//왜 {}를 붙여야 하는가. -> 익명 클래스의 인스턴스를 만들어서 익명 클래스가 상속하는 super class의 generic type parameter정보를 전달하기 위한 이유입니다. 
ParameterizedTypeReference type = new ParameterizedTypeReference<List<Map<Set<Integer>,String>>>() {};
System.out.println(typeRef.getType());
}
}
</code>
//사용하는 일 
//reflection에 대한 감은 필요. 
<code>

@SpringBootApplication
public class TobytvApplication {
public static void main(String[] args) {
SpringApplication.run(TobytvApplication.class,args);
}

@RestController
public static class MyController { 
@RequestMapping("/")
public List<User> users(){
//json의 루트가 array로 된다. 
return Arrays.asList(new User("A"), new User("B"), new User("C"));

}
}

public static class User {
String name;

public User(String name) {
this.name = name;
}

public User() {

}

}
}

// 이걸 resttemplate으로 끌어올 때 
public class SpringTypeReference {
public static void main(String[] args){
RestTemplate rt = new Resttemplate();
//List.class 가 type token이다. generic이 없을때 용이하다. 
//Linked hashMap으로 바뀐다.  List<User>라는걸 몰라서 가장 가까운 녀석으로 출력한다.  map.
//그래서 아래 안되! 
List<User> users = rt.getForObject("http://localhost:8080", List.class);

//exchange는 header와 http status, body를 다 가지고 있는 entity를 가지고 있어서 get body 이용. 
List<User> users = rt.exchange("http://localhost:8080", HttpMethod.get, null, new ParameterizedTypeReference<List<User>>() {}).getBody();
System.out.println(users.get(0).getName());

users.forEach(System.out::pringln);
}
}
</code>

new ParameterizedTypeReference<List<User>>() {}
매번 만들어야 하니까 한번 캐시 하거나 변수에 저장하는 방법도 좋을것같다. 


<code>
@SpringBootApplication 
public class TobyApplication{
static class GenericService<T> {
T t;

@PostConstruct
void init(){
Class tType;
t = ctx.getBean(tType);
}
}

@Component 
static class MyService extends GenericService<MyBean1> {
}

@Component 
static class MyService2 extends GenericService<MyBean2> {
}
}

</code>
spring 4.2부터 가능 .
<code>
@SpringBootApplication 
public class TobyApplication{

static class GenericService<T> {
@Autowired
T t;

@Autowired
R r;

@Autowired
S s;

}

@Component 
static class MyService extends GenericService<MyBean1> {
}

@Component 
static class MyService2 extends GenericService<MyBean2> {
}
}

</code>

1 2 3