1. 스프링 프레임워크 시작하기

1.1. 개발환경 구축

1.1.1. JDK 설치 및 환경 변수 설정

1.1.2. 이클립스(Eclipse) 설치

1.1.3. 톰캣(Tomcat) 서버 설치 및 이클립스 연동

1.1.4. 데이터베이스(DBMS) 서버 설치

USERS.sql

CREATE TABLE `users` (
  `ID` varchar2(8) PRIMARY KEY,
  `PASSWORD` varchar2(8),
  `NAME` varchar2(20),
  `ROLE` varchar2(5)
);

CREATE TABLE `users` (
  `ID` varchar(8) NOT NULL,
  `PASSWORD` varchar(8) NOT NULL,
  `NAME` varchar(20) NOT NULL,
  `ROLE` varchar(5) NOT NULL,
  PRIMARY KEY (`ID`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;



INSERT INTO USERS VALUES('admin','1111', 'admin','Admin');
INSERT INTO USERS VALUES('hong','1234','홍길동','User');

SELECT * FROM USERS ORDER BY ID;

BOARD.sql

CREATE TABLE BOARD(
SEQ NUMBER(5) PRIMARY KEY,
TITLE VARCHAR2(200),
WRITER VARCHAR2(20),
CONTENT VARCHAR2(2000),
REGDATE DATE DEFAULT SYSDATE,
CNT NUMBER(5) DEFAULT 0
);

CREATE TABLE BOARD(
SEQ int PRIMARY KEY,
TITLE VARCHAR(200),
WRITER VARCHAR(20),
CONTENT VARCHAR(2000),
REGDATE datetime DEFAULT current_timestamp,
CNT int DEFAULT 0
);
INSERT INTO BOARD(SEQ, TITLE, WRITER, CONTENT) VALUES(1,'title1','writer1','content1');
INSERT INTO BOARD(SEQ, TITLE, WRITER, CONTENT) VALUES(2,'title2','writer2','content2');

SELECT * FROM BOARD ORDER BY SEQ;

1.1.5 STS(Spring Tool Suite)

1.2. 프로젝트 생성

1.2.1 프로젝트 생성

1.2.2 프로젝트 설정 변경

<org.springframework-version>4.3.25.RELEASE</org.springframework-version>

메이븐레포지토리 최신 버전

<!-- https://mvnrepository.com/artifact/org.springframework/spring-context -->
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-context</artifactId>
    <version>4.3.30.RELEASE</version>
</dependency>
  1. 스프링 프레임워크 개요

2.1 프레임워크

2.1.1 개념

2.1.2 장점

2.1.3 자바 기반의 프레임워크

Presentation 영역

Business 영역

Persistence 영역

2.2. 스프링 프레임워크

2.2.1 탄생 배경

2.2.2 특징

경량

제어의 역행(Inversion of Control, IoC)

관점지향 프로그래밍(Aspect Oriented Programming, AOP)

컨테이너(Container)

2.3 IoC(Inversion Of Control) 컨테이너

1) WEB-INF/web.xml 파일을 로딩하여 구동
2) 브라우저로부터 /hello.do
3) hello.HelloServlet 클래스를 찾아 객체를 생성하고 doGet() 메서드 호출
4) doGet() 메서드 실행 결과를 클라이언트 브라우저로 전송
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee https://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" version="2.5">
  <servlet>
    <description></description>
    <display-name>hello</display-name>
    <servlet-name>hello</servlet-name>
    <servlet-class>com.springbook.biz.HelloService</servlet-class>
  </servlet>
  <servlet-mapping>
    <servlet-name>hello</servlet-name>
    <url-pattern>/hello.do</url-pattern>
  </servlet-mapping>
</web-app>
package com.springbook.biz;

import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class HelloService extends HttpServlet {
    private static final long serialVersionUID = 1L;

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // TODO Auto-generated method stub
        response.getWriter().append("Served at: ").append(request.getContextPath());
    }

}

2.3.1 결합도(Coupling) 높은 프로그램

SamsungTV.java

package polymorphism;

public class SamsungTV {

    public void powerOn() {
        System.out.println("SS - Power On");
    }

    public void powerOff() {
        System.out.println("SS - Power Off");
    }

    public void volumeUp() {
        System.out.println("SS - Volume Up");
    }

    public void volumeDown() {
        System.out.println("SS - Volume Down");
    }
}

LgTV.java

package polymorphism;

public class LgTV {

    public void turnOn() {
        System.out.println("LG - Turn On");
    }

    public void turnOff() {
        System.out.println("LG - Turn Off");
    }

    public void soundUp() {
        System.out.println("LG - Sound Up");
    }

    public void soundDown() {
        System.out.println("LG - Sound Down");
    }
}

TVUser.java

package polymorphism;

public class TVUser {

    public static void main(String[] args) {
        SamsungTV tv = new SamsungTV();
        tv.powerOn();
        tv.volumeDown();
        tv.volumeUp();
        tv.powerOff();

    }

}

TVUser.java

package polymorphism;

public class TVUser {

    public static void main(String[] args) {
        LgTV tv = new LgTV();
        tv.turnOn();
        tv.turnOff();
        tv.soundDown();
        tv.soundUp();

    }

}

2.3.2 다형성 이용하기

TV.java

package polymorphism;

public interface TV {

    public void powerOn();
    public void powerOff();
    public void volumeUp();
    public void volumeDown();
}

SamsungTV2.java

package polymorphism;

public class SamsungTV2 implements TV{

    public void powerOn() {
        System.out.println("SS - Power On");
    }

    public void powerOff() {
        System.out.println("SS - Power Off");
    }

    public void volumeUp() {
        System.out.println("SS - Volume Up");
    }

    public void volumeDown() {
        System.out.println("SS - Volume Down");
    }
}

LgTV2.java

package polymorphism;

public class LgTV2 implements TV{

    public void powerOn() {
        System.out.println("LG - Power On");
    }

    public void powerOff() {
        System.out.println("LG - Power Off");
    }

    public void volumeUp() {
        System.out.println("LG - Volume Up");
    }

    public void volumeDown() {
        System.out.println("LG - Volume Down");
    }
}

TVUser2.java

package polymorphism;

public class TVUser2 {

    public static void main(String[] args) {
        TV tv = new SamsungTV2(); // LgTV2() 만 변경(소수 수정 필요)
        tv.powerOn();
        tv.volumeDown();
        tv.volumeUp();
        tv.powerOff();

    }

}

2.3.3 디자인 패턴 이용하기

BeanFactory.java

package polymorphism;

public class BeanFactory {
    public Object getBean(String beanName) {
        if(beanName.equals("samsung")) {
            return new SamsungTV2();
        }
        else if(beanName.equals("lg")){
            return new LgTV2();
        }

        return null;
    }
}

TVUser3.java

package polymorphism;

public class TVUser3 {

    public static void main(String[] args) {

        BeanFactory factory = new BeanFactory();
        TV tv = (TV)factory.getBean(args[0]); // 소스 수정 없음
        tv.powerOn();
        tv.volumeDown();
        tv.volumeUp();
        tv.powerOff();
    }

}
  1. 스프링 컨테이너 및 설정 파일

  2. 대부분 IoC 컨테이너는 컨터이너에서 관리할 객체들을 위한 별도 설정 파일이 있음

  3. Servlet 컨테이너 : web.xml

3.1 스프링 IoC

3.1.1 스프링 설정 파일 생성

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

    <bean id="tv" class="polymorphism.SamsungTV2" />

</beans>

3.1.2 스프링 컨테이너 구동 및 테스트

TVUser4.java

package polymorphism;

import org.springframework.context.support.AbstractApplicationContext;
import org.springframework.context.support.GenericXmlApplicationContext;

public class TVUser4 {

    public static void main(String[] args) {

        // 1. Spring 컨테이너 중 하나인 GenericXmlApplicationContext 구동
        AbstractApplicationContext factory = new GenericXmlApplicationContext("applicationContext.xml");
    }

}
INFO : org.springframework.beans.factory.xml.XmlBeanDefinitionReader - Loading XML bean definitions from class path resource [applicationContext.xml]
INFO : org.springframework.context.support.GenericXmlApplicationContext - Refreshing org.springframework.context.support.GenericXmlApplicationContext@6c9f5c0d: startup date [Tue Jan 26 14:06:30 KST 2021]; root of context hierarchy

TVUser4.java

package polymorphism;

import org.springframework.context.support.AbstractApplicationContext;
import org.springframework.context.support.GenericXmlApplicationContext;

public class TVUser4 {

    public static void main(String[] args) {

        // 1. Spring 컨테이너 중 하나아니 GenericXmlApplicationContext 구동
        AbstractApplicationContext factory = new GenericXmlApplicationContext("applicationContext.xml");

        // 2. Spring 컨테이너로부터 필요한 객체 요청(Lookup)
        TV tv = (TV)factory.getBean("tv"); // <bean id="tv" ...>
        tv.powerOn();
        tv.volumeDown();
        tv.volumeUp();
        tv.powerOff();

        // 3. Spring 컨테이너 종료
        factory.close();

    }

}

3.1.3 스프링 컨테이너 종류

BeanFactory 컨테이너

ApplicationContext 컨테이너

3.2 스프링 XML 설정

3.2.1 루트 엘리먼트

3.2.2 엘리먼트

context-datasource.xml

<beans>
    DataSource 관련 설정
</beans>

context-transaction.xml

<beans>
    Transaction 관련 설정
</beans>

applicationContext.xml

<beans>
    <import resource="context-datasource.xml" />
    <import resource="context-transaction.xml" />
</beans>

3.2.3 엘리먼트

3.2.4 엘리먼트 속성

(1) init-method 속성

SamsungTV2.java

public void initMethod() {
        System.out.println("initMethod() 호출");
    }

applicationContext.xml

<bean name="tv" class="polymorphism.SamsungTV2" init-method="initMethod" />

(2) destroy-method 속성

SamsungTV2.java

public void destroyMethod() {
        System.out.println("destroyMethod() 호출");
    }

applicationContext.xml

<bean name="tv" class="polymorphism.SamsungTV2" init-method="initMethod" destroy-method="destroyMethod" />

(3) lazy-init 속성

(4) scope 속성

<bean name="tv" class="polymorphism.SamsungTV2" init-method="initMethod" destroy-method="destroyMethod" lazy-init="true"  scope="prototype" />

TVUser4.java

package polymorphism;

import org.springframework.context.support.AbstractApplicationContext;
import org.springframework.context.support.GenericXmlApplicationContext;

public class TVUser4 {

    public static void main(String[] args) {

        // 1. Spring 컨테이너 중 하나아니 GenericXmlApplicationContext 구동
        AbstractApplicationContext factory = new GenericXmlApplicationContext("applicationContext.xml");

        // 2. Spring 컨테이너로부터 필요한 객체 요청(Lookup)
        TV tv = (TV)factory.getBean("tv");
        TV tv1 = (TV)factory.getBean("tv");
        TV tv2 = (TV)factory.getBean("tv");

        tv.powerOn();
        tv.volumeDown();
        tv.volumeUp();
        tv.powerOff();



        // 3. Spring 컨테이너 종료
        factory.close();

    }

}
  1. 의존성 주입(Dependency Injection)

4.1 의존성 관리

4.1.1 스프링의 의존성 관리 방법

Dependency Lookup

Dependency Injection

4.1.2 의존성 관계

의존성 관계

SamsungTV에서 사용할 SonySpeaker 클래스 추가

package polymorphism;

public class SonySpeaker {
    public SonySpeaker() {
        System.out.println("SonySpeaker() 생성");
    }

    public void volumeUp() {
        System.out.println("SonySpeaker volumeUp() ");
    }

    public void volumeDown() {
        System.out.println("SonySpeaker volumeDown() ");
    }
}

SamsungTV 볼륨기능 클래스 추가

package polymorphism;

public class SamsungTV3 implements TV{

    private SonySpeaker speaker = null;

    public SamsungTV3() {
        System.out.println("SamsungTV() 생성");
    }

    public void powerOn() {
        System.out.println("Power On");
    }

    public void powerOff() {
        System.out.println("Power Off");
    }

    public void volumeUp() {
        speaker = new SonySpeaker();
        speaker.volumeUp();
    }

    public void volumeDown() {
        speaker = new SonySpeaker();
        speaker.volumeDown();
    }
}

테스트

applicationContext.xml

<bean name="tv3" class="polymorphism.SamsungTV3"  />

TVUser5.java

package polymorphism;

import org.springframework.context.support.AbstractApplicationContext;
import org.springframework.context.support.GenericXmlApplicationContext;

public class TVUser5 {

    public static void main(String[] args) {

        // 1. Spring 컨테이너 중 하나아니 GenericXmlApplicationContext 구동
        AbstractApplicationContext factory = new GenericXmlApplicationContext("applicationContext.xml");

        // 2. Spring 컨테이너로부터 필요한 객체 요청(Lookup)
        TV tv = (TV)factory.getBean("tv3");

        tv.powerOn();
        tv.volumeDown();
        tv.volumeUp();
        tv.powerOff();



        // 3. Spring 컨테이너 종료
        factory.close();

    }

}

4.2 생성자 인젝션 사용

SamsungTV 생성자에 SonySpeaker 매개변수 추가

SamsungTV4.java

package polymorphism;

public class SamsungTV4 implements TV{

    private SonySpeaker speaker = null;

    public SamsungTV4() {
        System.out.println("SamsungTV() 생성");
    }

    public SamsungTV4(SonySpeaker speaker) {
        System.out.println("SamsungTV(SonySpeaker speaker) 생성");
        this.speaker = speaker;
    }

    public void powerOn() {
        System.out.println("Power On");
    }

    public void powerOff() {
        System.out.println("Power Off");
    }

    public void volumeUp() {
        speaker.volumeUp();
    }

    public void volumeDown() {
        speaker.volumeDown();
    }
}

테스트

applicationContext.xml

<bean id="tv4" class="polymorphism.SamsungTV4">
        <constructor-arg ref="sony" />
</bean>
<bean id="sony" class="polymorphism.SonySpeaker" />

TVUser5.java

package polymorphism;

import org.springframework.context.support.AbstractApplicationContext;
import org.springframework.context.support.GenericXmlApplicationContext;

public class TVUser5 {

    public static void main(String[] args) {

        // 1. Spring 컨테이너 중 하나아니 GenericXmlApplicationContext 구동
        AbstractApplicationContext factory = new GenericXmlApplicationContext("applicationContext.xml");

        // 2. Spring 컨테이너로부터 필요한 객체 요청(Lookup)
        TV tv = (TV)factory.getBean("tv4");

        tv.powerOn();
        tv.volumeDown();
        tv.volumeUp();
        tv.powerOff();



        // 3. Spring 컨테이너 종료
        factory.close();

    }

}

4.2.1 다중 변수 매핑

맴버변수 추가 및 생성자 오버로딩

SamsungTV5.java

package polymorphism;

public class SamsungTV5 implements TV{

    private SonySpeaker speaker = null;
    private int price;

    public SamsungTV5() {
        System.out.println("SamsungTV5() 생성");
    }

    public SamsungTV5(SonySpeaker speaker) {
        System.out.println("SamsungTV5() 생성");
        this.speaker = speaker;
    }

    public SamsungTV5(SonySpeaker speaker, int price) {
        System.out.println("SamsungTV5() 생성");
        this.speaker = speaker;
        this.price = price;
        System.out.println("price="+this.price);
    }

    public void powerOn() {
        System.out.println("Power On");
    }

    public void powerOff() {
        System.out.println("Power Off");
    }

    public void volumeUp() {
        speaker.volumeUp();
    }

    public void volumeDown() {
        speaker.volumeDown();
    }
}

applicationContext.xml

<bean id="tv5" class="polymorphism.SamsungTV5">
        <constructor-arg ref="sony" />
        <constructor-arg value="1000000" />

    </bean>
    <bean id="sony" class="polymorphism.SonySpeaker" />

테스트 TVUser5.java

package polymorphism;

import org.springframework.context.support.AbstractApplicationContext;
import org.springframework.context.support.GenericXmlApplicationContext;

public class TVUser5 {

    public static void main(String[] args) {

        // 1. Spring 컨테이너 중 하나아니 GenericXmlApplicationContext 구동
        AbstractApplicationContext factory = new GenericXmlApplicationContext("applicationContext.xml");

        // 2. Spring 컨테이너로부터 필요한 객체 요청(Lookup)
        TV tv = (TV)factory.getBean("tv5");

        tv.powerOn();
        tv.volumeDown();
        tv.volumeUp();
        tv.powerOff();



        // 3. Spring 컨테이너 종료
        factory.close();

    }

}

4.2.2. 의존관계 변경

Speaker 인터페이스 추가

Speaker.java

package polymorphism;

public interface Speaker {
    void volumeUp();
    void volumeDown();
}

SonySpeaker 에 인터페이스 구현

SonySpeaker.java

package polymorphism;

public class SonySpeaker implements Speaker{
    public SonySpeaker() {
        System.out.println("SonySpeaker() 생성");
    }

    @Override
    public void volumeUp() {
        System.out.println("SonySpeaker volumeUp() ");
    }

    @Override
    public void volumeDown() {
        System.out.println("SonySpeaker volumeDown() ");
    }
}

SonySpeaker 참조 Speaker 참조로 소스 수정

SamsungTV6.java

package polymorphism;

public class SamsungTV6 implements TV{

    private Speaker speaker = null;
    private int price;

    public SamsungTV6() {
        System.out.println("SamsungTV6() 생성");
    }

    public SamsungTV6(Speaker speaker) {
        System.out.println("SamsungTV6() 생성");
        this.speaker = speaker;
    }

    public SamsungTV6(Speaker speaker, int price) {
        System.out.println("SamsungTV6() 생성");
        this.speaker = speaker;
        this.price = price;
        System.out.println("price="+this.price);
    }

    public void powerOn() {
        System.out.println("Power On");
    }

    public void powerOff() {
        System.out.println("Power Off");
    }

    public void volumeUp() {
        speaker.volumeUp();
    }

    public void volumeDown() {
        speaker.volumeDown();
    }
}

AppleSpeaker 추가 AppleSpeaker.java

package polymorphism;

public class AppleSpeaker implements Speaker{
    public AppleSpeaker() {
        System.out.println("AppleSpeaker() 생성");
    }

    @Override
    public void volumeUp() {
        System.out.println("AppleSpeaker volumeUp() ");
    }

    @Override
    public void volumeDown() {
        System.out.println("AppleSpeaker volumeDown() ");
    }
}

테스트

applicationContext.xml

<bean id="tv6" class="polymorphism.SamsungTV5">
        <constructor-arg ref="apple" />
        <constructor-arg value="1000000" />

</bean>
<bean id="sony" class="polymorphism.SonySpeaker" />
<bean id="apple" class="polymorphism.AppleSpeaker" />

TVUser6.java

package polymorphism;

import org.springframework.context.support.AbstractApplicationContext;
import org.springframework.context.support.GenericXmlApplicationContext;

public class TVUser6 {

    public static void main(String[] args) {

        // 1. Spring 컨테이너 중 하나아니 GenericXmlApplicationContext 구동
        AbstractApplicationContext factory = new GenericXmlApplicationContext("applicationContext.xml");

        // 2. Spring 컨테이너로부터 필요한 객체 요청(Lookup)
        TV tv = (TV)factory.getBean("tv6");

        tv.powerOn();
        tv.volumeDown();
        tv.volumeUp();
        tv.powerOff();



        // 3. Spring 컨테이너 종료
        factory.close();

    }

}

4.3 Setter 인젝션 사용하기

4.3.1. Setter 인젝션 기본

SamsungTV에 Setter 메소드 추가

SamsungTV7.java

package polymorphism;

public class SamsungTV7 implements TV{

    private Speaker speaker = null;
    private int price;

    public SamsungTV7() {
        System.out.println("SamsungTV7() 생성");
    }

    public void setSpeaker(Speaker speaker) {
        System.out.println("setSpeaker()");
        this.speaker = speaker;
    }

    public void setPrice(int price) {
        System.out.println("setPrice()");
        this.price = price;
    }

    public void powerOn() {
        System.out.println("Power On");
    }

    public void powerOff() {
        System.out.println("Power Off");
    }

    public void volumeUp() {
        speaker.volumeUp();
    }

    public void volumeDown() {
        speaker.volumeDown();
    }
}

테스트

applicationContext.xml

<bean id="tv7" class="polymorphism.SamsungTV7">
    <property name="speaker" ref="apple"></property>
    <property name="price" value="1000000"></property>

</bean>
<bean id="sony" class="polymorphism.SonySpeaker" />
<bean id="apple" class="polymorphism.AppleSpeaker" />

TVUser7.java

package polymorphism;

import org.springframework.context.support.AbstractApplicationContext;
import org.springframework.context.support.GenericXmlApplicationContext;

public class TVUser7 {

    public static void main(String[] args) {

        // 1. Spring 컨테이너 중 하나아니 GenericXmlApplicationContext 구동
        AbstractApplicationContext factory = new GenericXmlApplicationContext("applicationContext.xml");

        // 2. Spring 컨테이너로부터 필요한 객체 요청(Lookup)
        TV tv = (TV)factory.getBean("tv7");

        tv.powerOn();
        tv.volumeDown();
        tv.volumeUp();
        tv.powerOff();



        // 3. Spring 컨테이너 종료
        factory.close();

    }

}

4.3.2 p 네임스페이스 사용하기

applicationContext.xml

<bean id="tv7" class="polymorphism.SamsungTV7" p:speaker-ref="sony" p:price="1000000" />
<bean id="sony" class="polymorphism.SonySpeaker" />
<bean id="apple" class="polymorphism.AppleSpeaker" />

4.4 컬렉션(Collection) 객체 설정

4.4.1 List 타입 매핑

CollectionBean.java

package com.springbook.ioc.injection;

import java.util.List;

public class CollectionBean {
    private List<String> addressList;

    public List<String> getAddressList() {
        return addressList;
    }

    public void setAddressList(List<String> addressList) {
        this.addressList = addressList;
    }
}

테스트

applicationContext.xml

<bean id="collectionBean" class="kr.thecoding.spring.ioc.indection.CollectionBean">
    <property name="addressList">
        <list>
            <value>서울시</value>
            <value>경기도</value>
            <value>제주도</value>
        </list>
    </property>
</bean>

CollectionBeanTest.java

package kr.thecoding.spring.ioc.indection;

import java.util.List;

import org.springframework.context.support.AbstractApplicationContext;
import org.springframework.context.support.GenericXmlApplicationContext;

public class CollectionBeanTest {
    public static void main(String[] args) {
        AbstractApplicationContext factory = new GenericXmlApplicationContext("applicationContext.xml");

        CollectionBean bean = (CollectionBean)factory.getBean("collectionBean");
        List<String> addressList = bean.getAddressList();
        for(String address : addressList) {
            System.out.println(address);
        }

        factory.close();

    }



}

4.4.2 Set 타입 매핑

CollectionBean.java

package kr.thecoding.spring.ioc.indection;

import java.util.List;
import java.util.Set;

public class CollectionBean {
    private List<String> addressList;
    private Set<String> addressSet;

    public List<String> getAddressList() {
        return addressList;
    }

    public void setAddressList(List<String> addressList) {
        this.addressList = addressList;
    }

    public Set<String> getAddressSet() {
        return addressSet;
    }

    public void setAddressSet(Set<String> addressSet) {
        this.addressSet = addressSet;
    }


}

테스트

applicationContext.xml

<bean id="collectionBean" class="kr.thecoding.spring.ioc.indection.CollectionBean">
    <property name="addressList">
        <list>
            <value>서울시</value>
            <value>경기도</value>
            <value>제주도</value>
        </list>
    </property>

    <property name="addressSet">
        <set>
            <value>서울시</value>
            <value>경기도</value>
            <value>서울시</value>
        </set>
    </property>

</bean>

CollectionBeanTest.java

package kr.thecoding.spring.ioc.indection;

import java.util.List;
import java.util.Set;

import org.springframework.context.support.AbstractApplicationContext;
import org.springframework.context.support.GenericXmlApplicationContext;

public class CollectionBeanTest {
    public static void main(String[] args) {
        AbstractApplicationContext factory = new GenericXmlApplicationContext("applicationContext.xml");

        CollectionBean bean = (CollectionBean)factory.getBean("collectionBean");

        List<String> addressList = bean.getAddressList();
        for(String address : addressList) {
            System.out.println(address);
        }

        Set<String> addressSet = bean.getAddressSet();
        for(String address : addressSet) {
            System.out.println(address);
        }

        factory.close();

    }



}

4.4.3 Map 타입 매핑

CollectionBean.java

package kr.thecoding.spring.ioc.indection;

import java.util.List;
import java.util.Map;
import java.util.Set;

public class CollectionBean {
    private List<String> addressList;
    private Set<String> addressSet;
    private Map<String, String> addressMap;

    public List<String> getAddressList() {
        return addressList;
    }

    public void setAddressList(List<String> addressList) {
        this.addressList = addressList;
    }

    public Set<String> getAddressSet() {
        return addressSet;
    }

    public void setAddressSet(Set<String> addressSet) {
        this.addressSet = addressSet;
    }

    public Map<String, String> getAddressMap() {
        return addressMap;
    }

    public void setAddressMap(Map<String, String> addressMap) {
        this.addressMap = addressMap;
    }



}

테스트

applicationContext.xml

<bean id="collectionBean" class="kr.thecoding.spring.ioc.indection.CollectionBean">
    <property name="addressList">
        <list>
            <value>서울시</value>
            <value>경기도</value>
            <value>제주도</value>
        </list>
    </property>

    <property name="addressSet">
        <set>
            <value>서울시</value>
            <value>경기도</value>
            <value>서울시</value>
        </set>
    </property>

    <property name="addressMap">
        <map>
            <entry>
                <key><value>고구려</value></key>
                <value>평양</value>
            </entry>

            <entry>
                <key><value>신라</value></key>
                <value>경주</value>
            </entry>

            <entry>
                <key><value>백제</value></key>
                <value>부여</value>
            </entry>

        </map>
    </property>

</bean>

CollectionBeanTest.java

package kr.thecoding.spring.ioc.indection;

import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;

import org.springframework.context.support.AbstractApplicationContext;
import org.springframework.context.support.GenericXmlApplicationContext;

public class CollectionBeanTest {
    public static void main(String[] args) {
        AbstractApplicationContext factory = new GenericXmlApplicationContext("applicationContext.xml");

        CollectionBean bean = (CollectionBean)factory.getBean("collectionBean");

        List<String> addressList = bean.getAddressList();
        for(String address : addressList) {
            System.out.println(address);
        }

        Set<String> addressSet = bean.getAddressSet();
        for(String address : addressSet) {
            System.out.println(address);
        }

        Map<String, String> addressMap = bean.getAddressMap();
        System.out.println(addressMap.get("고구려"));
        Set<Entry<String, String>> set = addressMap.entrySet();
        Iterator<Entry<String, String>> it = set.iterator();

        while(it.hasNext()) {
            Map.Entry<String, String> e = (Map.Entry<String, String>)it.next();
            System.out.println("나라 : "+ e.getKey() + ", 수도 : " + e.getValue());
        }


        factory.close();

    }



}

참고 : Map 사용법

4.4.4 Properties 타입 매핑

CollectionBean.java

package kr.thecoding.spring.ioc.indection;

import java.util.List;
import java.util.Map;
import java.util.Set;

public class CollectionBean {
    private List<String> addressList;
    private Set<String> addressSet;
    private Map<String, String> addressMap;
    private Properties addressProp;

    public List<String> getAddressList() {
        return addressList;
    }

    public void setAddressList(List<String> addressList) {
        this.addressList = addressList;
    }

    public Set<String> getAddressSet() {
        return addressSet;
    }

    public void setAddressSet(Set<String> addressSet) {
        this.addressSet = addressSet;
    }

    public Map<String, String> getAddressMap() {
        return addressMap;
    }

    public void setAddressMap(Map<String, String> addressMap) {
        this.addressMap = addressMap;
    }

    public Properties getAddressProp() {
        return addressProp;
    }

    public void setAddressProp(Properties addressProp) {
        this.addressProp = addressProp;
    }

    public Properties getAddressProp() {
        return addressProp;
    }

    public void setAddressProp(Properties addressProp) {
        this.addressProp = addressProp;
    }



}

테스트

applicationContext.xml

<bean id="collectionBean" class="kr.thecoding.spring.ioc.indection.CollectionBean">
    <property name="addressList">
        <list>
            <value>서울시</value>
            <value>경기도</value>
            <value>제주도</value>
        </list>
    </property>

    <property name="addressSet">
        <set>
            <value>서울시</value>
            <value>경기도</value>
            <value>서울시</value>
        </set>
    </property>

    <property name="addressMap">
        <map>
            <entry>
                <key><value>고구려</value></key>
                <value>평양</value>
            </entry>

            <entry>
                <key><value>신라</value></key>
                <value>경주</value>
            </entry>

            <entry>
                <key><value>백제</value></key>
                <value>부여</value>
            </entry>

        </map>
    </property>

    <property name="addressProp">

        <props>
            <prop key="고려">개성</prop>
            <prop key="조선">한양</prop>
            <prop key="대한민국">서울</prop>
        </props>

    </property>

</bean>

CollectionBeanTest.java

package kr.thecoding.spring.ioc.indection;

import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;

import org.springframework.context.support.AbstractApplicationContext;
import org.springframework.context.support.GenericXmlApplicationContext;

public class CollectionBeanTest {
    public static void main(String[] args) {
        AbstractApplicationContext factory = new GenericXmlApplicationContext("applicationContext.xml");

        CollectionBean bean = (CollectionBean)factory.getBean("collectionBean");

        List<String> addressList = bean.getAddressList();
        for(String address : addressList) {
            System.out.println(address);
        }

        Set<String> addressSet = bean.getAddressSet();
        for(String address : addressSet) {
            System.out.println(address);
        }

        Map<String, String> addressMap = bean.getAddressMap();
        System.out.println(addressMap.get("고구려"));
        Set<Entry<String, String>> set = addressMap.entrySet();
        Iterator<Entry<String, String>> it = set.iterator();

        while(it.hasNext()) {
            Map.Entry<String, String> e = (Map.Entry<String, String>)it.next();
            System.out.println("나라 : "+ e.getKey() + ", 수도 : " + e.getValue());
        }

        Properties addressProp = bean.getAddressProp();
        System.out.println(addressProp.getProperty("고구려"));
        Enumeration<?> e = addressProp.propertyNames();

        while(e.hasMoreElements()) {
            String country = (String)e.nextElement();
            System.out.println("나라 : "+ country + ", 수도 : " + addressProp.getProperty(country));
        }

        Iterator<?> eit = (Iterator<?>)addressProp.propertyNames();

        while(eit.hasNext()) {
            String country = (String)eit.next();
            System.out.println("나라 : "+ country + ", 수도 : " + addressProp.getProperty(country));
        }


        factory.close();

    }



}

05 어노테이션 기반 설정

5.1 어노테이션 설정

5.1.1 Context 네임스페이스 추가

xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.2.xsd"

5.1.2 컴포넌트 스캔(component-scan) 설정

applicationContext.xml

<context:component-scan base-package="polymorphism"></context:component-scan>

LgTV.java

package polymorphism;

import org.springframework.stereotype.Component;

@Component("tv")
public class LgTV implements TV{

    @Override
    public void powerOn() {
        // TODO Auto-generated method stub

    }

    @Override
    public void powerOff() {
        // TODO Auto-generated method stub

    }

    @Override
    public void volumeUp() {
        // TODO Auto-generated method stub

    }

    @Override
    public void volumeDown() {
        // TODO Auto-generated method stub

    }


}

TVUser7.java

package polymorphism;

import org.springframework.context.support.AbstractApplicationContext;
import org.springframework.context.support.GenericXmlApplicationContext;

public class TVUser7 {

    public static void main(String[] args) {

        // 1. Spring 컨테이너 중 하나아니 GenericXmlApplicationContext 구동
        AbstractApplicationContext factory = new GenericXmlApplicationContext("applicationContext.xml");

        // 2. Spring 컨테이너로부터 필요한 객체 요청
        TV tv = (TV)factory.getBean("tv");


        // 3. Spring 컨테이너 종료
        factory.close();

    }

}

5.2 의존성 주입 설정

5.2.1 의존성 주입 어노테이션

5.2.2 @Autowired

LgTV에 Speaker 멤버변수 와 @Autowired 추가 LgTV.java

package polymorphism;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

@Component("tv")
public class LgTV implements TV{

    @Autowired
    private Speaker speaker;

    @Override
    public void powerOn() {
        // TODO Auto-generated method stub

    }

    @Override
    public void powerOff() {
        // TODO Auto-generated method stub

    }

    @Override
    public void volumeUp() {


    }

    @Override
    public void volumeDown() {
        // TODO Auto-generated method stub

    }


}

테스트

TVUser7.java

package polymorphism;

import org.springframework.context.support.AbstractApplicationContext;
import org.springframework.context.support.GenericXmlApplicationContext;

public class TVUser7 {

    public static void main(String[] args) {

        // 1. Spring 컨테이너 중 하나아니 GenericXmlApplicationContext 구동
        AbstractApplicationContext factory = new GenericXmlApplicationContext("applicationContext.xml");

        // 2. Spring 컨테이너로부터 필요한 객체 요청
        TV tv = (TV)factory.getBean("tv");


        // 3. Spring 컨테이너 종료
        factory.close();

    }

}

Speaker 객체 생성(sony) 추가 후 재 테스트

package polymorphism;

import org.springframework.stereotype.Component;

@Component("sony")
public class SonySpeaker implements Speaker{

    public SonySpeaker() {
        System.out.println("SonySpeaker() 생성");
    }

    public void volumeUp() {
        System.out.println("SonySpeaker volumeUp() ");
    }

    public void volumeDown() {
        System.out.println("SonySpeaker volumeDown() ");
    }
}

Speaker 객체 생성(apple) 추가 후 재 테스트

AppleSpeaker.java

package polymorphism;

import org.springframework.stereotype.Component;

@Component("apple")
public class AppleSpeaker implements Speaker{

    public AppleSpeaker() {
        System.out.println("AppleSpeaker() 생성");
    }

    public void volumeUp() {
        System.out.println("AppleSpeaker volumeUp() ");
    }

    public void volumeDown() {
        System.out.println("AppleSpeaker volumeDown() ");
    }
}

5.2.3 @Qualifier

LgTV.java

package polymorphism;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Component;

@Component("tv")
public class LgTV implements TV{

    @Autowired
    @Qualifier("apple")
    private Speaker speaker;

    public LgTV() {
        System.out.println("LgTV() 생성");
    }

    @Override
    public void powerOn() {
        // TODO Auto-generated method stub

    }

    @Override
    public void powerOff() {
        // TODO Auto-generated method stub

    }

    @Override
    public void volumeUp() {
        // TODO Auto-generated method stub

    }

    @Override
    public void volumeDown() {
        // TODO Auto-generated method stub

    }


}

5.2.3 @Resource

<dependency>
    <groupId>javax.annotation</groupId>
    <artifactId>javax.annotation-api</artifactId>
    <version>1.3.2</version>
</dependency>

LgTV.java

//@Autowired
//@Qualifier("apple")
@Resource(name="apple")
private Speaker speaker;

5.2.5 어노테이션과 XML 설정 병행하여 사용

LgTv.java

@Autowired
private Speaker speaker;

xml
<bean id="sony" class="polymorphism.SonySpeaker" />

5.3 추가 어노테이션

5.3.1 @Component를 상속하여 추가된 어노테이션

참고 : 애노테이션 정리 https://atoz-develop.tistory.com/entry/Spring-DI-%EC%95%A0%EB%85%B8%ED%85%8C%EC%9D%B4%EC%85%98-%EC%A0%95%EB%A6%AC-Autowired-Resource-Inject