티스토리 뷰

 

1. 객체간 의존성

객체의 사용에 의해 발생. 그동안은 클래스 안에서 만들어 객체 사용하는 자급자족.

>> 필요한 것을 밖에서 만들어서 주입하는 것 : 의존성 주입(DI)

 

>>의존성을 제거하는 방법 : XML 사용 / Annotation(@Override 방식) 사용 / Java Configuration

(*XML은 비친절.)

**Annotaion : 내가 직접 만들지 않은 것, 스프링이 자체적으로 제공하는 것들은 Annotation 못함.

  내가 직접 만든 것만으로 할 수 있음.

 


협업할 때, 작은 것부터 만들어서 나중에 취합.
그것에 적합한 것이 프레임워크.

전자정보 프레임워크 : 스프링 기반

분산 전체 EE / 웹 분산 Spring(가장 많이 쓰는 게 mvc)


2. DI와 IoC 컨테이너

(1) DI(Dependence Injection)

의존성 주입. 즉, Spring 프레임워크에서 지원하는 IoC 형태.

객체를 직접 생성하는 것이 아니라 외부에서 객체를 만들어서 주입시키는 방식.

왜냐하면,

협업할 때, 또는 프로젝트가 커지면 자급자족이 어려움. 따라서 외부에서 클래스를 만들어 주입.

 

(1-2) IoC(Inversion of Control, 제어권 역전)

객체의 생성, 생명주기의 관리 등 모든 객체에 대한 제어권이 바뀐 것.

인스턴스 생성부터 소멸까지의 인스턴스 생명 주기 관리를 개발자가 아닌 컨테이너가 대신하는 것.

 

(2)DI를 위한 설정(종류)

(2-1) 기존의 일체형. 자급자족.

객체 일일이 만들어서 접근. Dao 클래스를 추가하면 UI 코드도 수정해야 함.

UI Service   Dao    
디비
A / B
S A1
B1
  B2
private B1 b = new B1();
b.getData();

private B2 b = new B1();
b.getData();

 

(2-2) 인터페이스 활용 - 결합력을 낮추는 방법 1

B1과 B2의 공통 속성을 가지는 Interface 정의

private B b = new B2();
g.getData();

└객체를 생성할 때, new 뒷부분만 바꾸면 됨.

 

(2-3) XML과 Annotation 활용

B b = new B();
service.set(b)

└new 뒷부분을 바꾸는 것도 싫어서 더욱 간단히 : 객체 생성과 조립을 위한 외부 설정 'DI' - XML, Annotation

(*자동완성이나 오타를 잡아주지 못해서 불편함)

→ Java Configuration으로 바꿀 수도 있음. XML을

 

(3) Dependency 조립하기

-DI와 IoC Controller : 종속 객체를 생성 조립해주는 도구(스프링프레임워크 코어 기능)

-실제로 값을 넣는 방법

//일체형 - Class A가 Class B를 가짐(B는 A의 부품). B는 A의 종속 객체(Dependency)
class A {
	private B b;
    
    public A(){
    	b = new B();
    }
}
//조립형 - ★결합력이 낮아 부품을 쉽게 갈아끼울 수 있음. 기업형에서 자주 사용
class A {
	private B b;
    
    public A(){
    }
    
    public void setB(B b){
    	this.b = b;
        //B는 다른 곳에서 만들어져 있음.
    }
}

(3-1) Dependency 조립 : 일체형

원래 하던 방식

A a = new A();

 

(3-2) Dependency 조립 : 조립형

조립형으로 부품을 갈아 끼우는 두 가지 방법. 실제 값을 넣는 방법.

-setter Injection : setter 이용

B b = new B();
A a = new A();
a.setB(b);

-Construction Injection : 생성자를 이용

B b = new B();
A a = new A(b);

 

>> 매번 조립하는 게 불편(단점) >> 조립을 해주는(DI) 서비스 역할의 도구 필요 : 스프링

 

 

(4) IoC(Inversion Of Controller)

객체를 담을 수 있는 그릇. 역순으로 객체 생성하는 컨테이너. 작은 부품 → 큰 부품 순으로 결합.

XML 파일, Annotaion 사용.

ex)

부품 구매 및 조립 주문서 작성 방법 : XML 파일, Annotation

주문서 내역대로 부품을 담는 컨테이너 : 부품 컨테이너 = IoC 컨테이너

 

-부품을 주문하면 만들어서 컨테이너에 담는다.

-부품끼리 조립해서 컨테이너에 담는다.

 

(5) 일체형과 조립형 DI 순서

(5-1) 일체형

부품이 만들어져서 결합될 때. 정방향으로 만들어져 결합.  A → B → C → D

 

(5-2) 조립형

부품이 만들어져서 결합될 때, 역순으로 만들어져서 결합.  A ← B ← C ← D

D가 먼저 만들어진 후, C가 만들어져서 D와 C가 결합. → B가 만들어지면 결합된 [D C]와 결합. → A가 만들어지면 결합된 [B C D]와 결합. ☞  Inversion of Control(제어 역행)으로 Container에 담는다. 즉, IoC Container

 


※ 실습 예제 ※

목표 : 일반 자바 프로젝트를 만들어서 스프링으로 바꾸기

1. 프로젝트 생성

-testDi01 / JRE 버전 : JavaSE - 1.8 / open perspective

 

2. 클래스 생성

(1) 실제 모델 역할하는 클래스 생성

-패키지 이름 : com.di.entity

-클래스 이름 : DiExam - 데이터와 비즈니스 로직 담는 객체

package com.di.entity;

public class DiExam {
	private int kor;
	private int eng;
	private int math;
	private int com;
	
	public int total() {
		return kor+eng+math+com;
	}
	public float avg() {
		return total()/4.0f; //4.0해줘서 실수로 결과 나옴.
	}
	//total, avg 출력 클래스 생성 >>
}

 

(2)  total, avg 출력 클래스 생성

-패키지 : com.di.ui

(2-1) 클래스 1 생성 :  LineExamConsloe - 출력 유형 1

package com.di.ui;

import com.di.entity.DiExam;

public class LineExamConsloe {
	//import DiExam
	private DiExam exam;
	//값을 set하는 함수
	public void setDiExam(DiExam exam) {
		this.exam = exam;
	}
	//exam 내용 출력 함수
	public void print() {
		System.out.printf("total is %d, avg is %f\n", exam.total(), exam.avg());
	}
}

(2-2) 클래스 2 생성 : GridExamConsole - 출력 유형2

package com.di.ui;

import com.di.entity.DiExam;

public class GridExamConsole {
	//import DiExam
	private DiExam exam;
		
	// 값을 set하는 함수
	public void setDiExam(DiExam exam) {
		this.exam = exam;
	}

	public void print() {
		System.out.println("┌──────────┬──────────┐");
		System.out.println("│ total    │ avg      │");
		System.out.println("├──────────┼──────────┤");
		System.out.printf("│ %3d      │ %3.2f     │\n", exam.total(), exam.avg());
		System.out.println("└──────────┴──────────┘");
	}
}

 

(3) 출력할 메인 함수 클래스 생성

-패키지 : com.di

-클래스 : App.java

package com.di;

import com.di.entity.DiExam;
import com.di.ui.GridExamConsole;

public class App {
	public static void main(String[] args) {
		DiExam exam = new DiExam();
		
		LineExamConsole console = new LineExamConsole();
//		GridExamConsole console = new GridExamConsole();
		console.setDiExam(exam);
		console.print();
	}
}

 

(4) 출력 결과

객체를 생성하고 값을 설정하고 출력.

(4-1) LineExamConsole() 출력 결과

total is 0, avg is 0.000000

 

(4-2) GridExamConsole() 출력 결과

>> DiExam 객체를 출력할 때, 종류(Line or Grid)에 따라 사용 방법이 다름.  LineExamConsole()을 사용하려면 LinsExamConsole() 객체를 생성해 호출해야 하며 Grid일 때도 마찬가지.

//LineExamConsole console = new LineExamConsole();
GridExamConsole console = new GridExamConsole();

이 번거로움이 프로젝트가 커질수록 심해질 것. 위처럼 사용방법을 변경하지 않아도 되도록 하는 것이 의존성 주입! 결합력을 느슨하게 해서.

 

>> 위의 예제를 가지고 Interface, XML, Annotation, Java Configuration로 의존성 주입(의존성 제거)

 


1. Interface에 의한 의존성 제거

(1) Grid/LineExamConlse과 diExam을 호출하기 위한 인터페이스 생성

다른 클래스를 만들었을때, 변화를 전파하지 않기 위해서. 앞으로 변화를 전파하지 않기 위해서.

(1-1) Exam 인터페이스 생성

-패키지 : com.di.entity

-인터페이스 이름 : Exam

package com.di.entity;

public interface Exam {
	public int total();
	public float avg();
}

>> DiExam 클래스에서 total(), avg()를 오버라이딩해줘야 함. Exam을 구현(implements)을 표시? 선언해주고

package com.di.entity;

public class DiExam implements Exam { //★
	private int kor;
	private int eng;
	private int math;
	private int com;
	
	@Override //★
	public int total() {
		return kor+eng+math+com;
	}
	@Override //★
	public float avg() {
		return total()/4.0f; //4.0해줘서 실수로 결과 나옴.
	}
}

 

(1-2) ExamConsole 인터페이스 생성

-패키지 : com.di.ui

package com.di.ui;

public interface ExamConsole {
	void print();
}

>> GrideExamConsole, LineExamConsole 클래스에서 ExamConsole을 구현하고 print() 오버라이딩해줘야 함.

package com.di.ui;
import com.di.entity.DiExam;
public class LineExamConsole implements ExamConsole { //★
	//import DiExam
	private DiExam exam;
    
	//값을 set하는 함수
	public void setDiExam(DiExam exam) {
		this.exam = exam;
	}
	@Override //★
	public void print() {
		System.out.printf("total is %d, avg is %f\n", exam.total(), exam.avg());
	}
}
//
package com.di.ui;
import com.di.entity.DiExam;
public class GridExamConsole implements ExamConsole { //★
	//import DiExam
	private DiExam exam;
		
	// 값을 set하는 함수
	public void setDiExam(DiExam exam) {
		this.exam = exam;
	}
	@Override  //★
	public void print() {
		System.out.println("┌──────────┬──────────┐");
		System.out.println("│ total    │ avg      │");
		System.out.println("├──────────┼──────────┤");
		System.out.printf("│ %3d      │ %3.2f     │\n", exam.total(), exam.avg());
		System.out.println("└──────────┴──────────┘");
	}
}

 

(2) 인터페이스로 객체 생성해 호출

package com.di;

import com.di.entity.DiExam;
import com.di.entity.Exam;
import com.di.ui.ExamConsole;
import com.di.ui.GridExamConsole;
import com.di.ui.LineExamConsole;

public class App {
	public static void main(String[] args) {
		//객체 생성 DiExam → 인터페이스 Exam 변경
		Exam exam = new DiExam(); //★
	
//		LineExamConsole console = new LineExamConsole();
//		GridExamConsole console = new GridExamConsole();

		//객체 생성 변경. new 뒷부분만 변경하면 됨.
		ExamConsole console =  new LineExamConsole();
        
		console.setExam(exam);
		console.print();
	}
}

위와 같은 방식을 하기 위해서 수정 : DiExam 클래스로 필드 생성했던 것을 인터페이스 Exam으로 변경

>> GridExamConsole() 변경

package com.di.ui;

import com.di.entity.Exam;

public class GridExamConsole implements ExamConsole {
	//private DiExam exam;
	private Exam exam; //★ - 인터페이스로 받을 수 있음.
		
	// 값을 set하는 함수
	public void setExam(Exam exam) {
		this.exam = exam;
	}
	@Override 
	public void print() {
		System.out.println("┌──────────┬──────────┐");
		System.out.println("│ total    │ avg      │");
		System.out.println("├──────────┼──────────┤");
		System.out.printf("│ %3d      │ %3.2f     │\n", exam.total(), exam.avg());
		System.out.println("└──────────┴──────────┘");
	}
}

>> LineExamConsole() 변경

package com.di.ui;

import com.di.entity.Exam;

public class LineExamConsole implements ExamConsole {
//	private DiExam exam;
	private Exam exam; //★
	
	//값을 set하는 함수
	public void setExam(Exam exam) {
		this.exam = exam;
	}
	
	//exam 내용 출력 함수
	@Override
	public void print() {
		System.out.printf("total is %d, avg is %f\n", exam.total(), exam.avg());
	}
}

>>ExamConsole 인터페이스에 내용 추가

package com.di.ui;

import com.di.entity.Exam;

public interface ExamConsole {
	void print();
	void setExam(Exam exam); //★
}

 

※ 외부에서 생성해서 주입하는 방법은,

컨테이너가 필요(*스프링을 사용할 수 있도록 플러그인 설치)

http://spring.io >> project : Spring Tools4 >> 사용하는 프로그램에 맞는 것

(mvc할 때 사용할 예정)

 

아래의 방법은 컨테이너를 생성하지 않는 방법.

아직 완전히 느슨해진 것은 아니기 때문에 완벽하게 하기 위해 xml 사용

(컨테이너 사용하지 않고 xml 사용하는 방법)

xml을 IoC 컨테이너로 사용하는 방법

 

2. XML 사용

(1) 이클립스 플러그인 설치

네임스페이스를 직접 입력하지 않기 위해서. (네임스페이스 : 주소 같은 것을 입력해주는 것인데, xml은 오타를 잡아주지 않아서 불편. 최근에는 거의 사용하지 않음)

 

이클립스 메뉴 : help >> Eclipse MarketPlace : spring 검색 >> Spring Toos 3 Add - on for Spring tools 4(두번째 것)

(*첫번째 것은 스프링부트) >> 설치 >> 동의 >> 이클립스 재시작 동의

 

-목적 : 아래쪽의 객체 생성하는 것을 외부(XML)에서 해서 주입할 것.

public static void main(String[] args) {
    //객체 생성
    Exam exam = new DiExam();
	
    //Grid냐 Line이냐에 따라 뒷부분만 바꾸면 됨.
    //아래의 생성을 외부에서 해서 주입하는 것.
    ExamConsole console =  new LineExamConsole();
    ExamConsole console =  new GridExamConsole();
    
    console.setExam(exam);
    console.print();
}

 

(2) 컨테이너 역할을 하는 DI를 XML로 만들 것.

-xml 생성 : com.di. 패키지 우클릭 >> spirng >> Spring Bean Configuration file >> setting.xml

>> 네임스페이스 자동 생성

<?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">
    
    <!--객체 생성하고 값을 넣으면 된다.-->
    
</beans>

(2-1) 용어 및 사용법

<bean id="변수(구분하는 역할)" class="빈을 만들 때 사용할 클래스(패키지명, 클래스 이름 full)"/>

<bean id="변수" class="빈을 만들 때 사용할 클래스">
	<property name="값을 가져올 것" ref="참조할 bean의 id"></property>
</bean>

 

(2-2) xml에서 생성

<?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">
	<!-- 순서 : exam 만들고 console 만듦어야 함. -->
	<!-- new DiExam() 대신-->
	<bean id="exam" class="com.di.entity.DiExam"/><!-- 객체 생성-->
	
	<!-- new LineExamConsole(); 대신-->
	<bean id="console" class="com.di.ui.LineExamConsole">
		<!-- exam 객체가 들어가야 함 -->
		<property name="exam" ref="exam"></property>
        <!--name="exam"은 LineExamConsole에서 setExam()을 찾음. 없으면 오류-->
        <!--직접 값을 넣을 땐 value 사용, 참조할 땐, ref="참조할 bean의 아이디"-->
	</bean>

	<!--이렇게 만들어진 것을 불러오는 뭔가가 있어야 하는데 >> App -->
</beans>

└class에는 패키지명과 클래스 이름 전부 다 적어줘야 함.

└이렇게 xml에서 만들어 진 것을 호출하는 것음 App.java

 

잠깐) 스프링을 설치했지만, 현재 프로젝트는 '자바'임.

프로젝트 우클릭 >>configure >> convert to maven project >> pom.xml 생성

(*pom.xml은 어떤 라이브러리가 필요한지 알려주면(입력해두면) 알아서 필요한 소스들을 다운받음)

(*메이븐, 그래들 : 프로젝트 빌드/관리 도구. 프로젝트를 관리하고 만들어주는 도구.)

(빌드 도구 '메이븐' 개인적으로 공부)

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>testDi01</groupId>
  <artifactId>testDi01</artifactId>
  <version>0.0.1-SNAPSHOT</version>
  
  <dependencies>
  	<!--version과 build 사이에 dependencies 입력.-->
  	<!--사용할 것을 알려주면(입력하면) 자동 다운로드-->
  </dependencies>
  
  <build>
    <sourceDirectory>src</sourceDirectory>
    <resources>
      <resource>
        <directory>src</directory>
        <excludes>
          <exclude>**/*.java</exclude>
        </excludes>
      </resource>
    </resources>
    <plugins>
      <plugin>
        <artifactId>maven-compiler-plugin</artifactId>
        <version>3.8.1</version>
        <configuration>
          <source>1.8</source>
          <target>1.8</target>
        </configuration>
      </plugin>
    </plugins>
  </build>
</project>

 

>> 현재, 메이븐 프로젝트 상태 >> 구글 검색 : maven repository(필요한 라이브러리 포함) >> Spring framework 검색 >> spring context 최신버전 다운받으면 됨(수업에선 5.2.19.RELEASE 다운) >> Maven의 코드 복사해서 디펜던시 사이에 붙여 넣기

<!-- https://mvnrepository.com/artifact/org.springframework/spring-context -->
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-context</artifactId>
    <version>5.2.19.RELEASE</version>
</dependency>

>> 오버뷰, 디펜던시즈, 등에서 확인. Maven dependecies 폴더 확인

 

(3) 호출 : App.java

위의 과정을 거쳐야 Application 사용할 수 있게 되었음.

(원래는 Application 자동 완성이 안 됐는데, 그건 라이브러리가 없었기 때문.)

package com.di;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import com.di.entity.DiExam;
import com.di.entity.Exam;
import com.di.ui.ExamConsole;
import com.di.ui.GridExamConsole;
import com.di.ui.LineExamConsole;

public class App {
	public static void main(String[] args) {
		                                                            //경로 설정
        ApplicationContext ctx = new ClassPathXmlApplicationContext("com/di/setting.xml");
        
        //1. id 적는 법. 리턴이 오브젝트형이라 타입캐스팅해줘야 함.
//      ExamConsole console = (ExamConsole)ctx.getBean("console");
		
        //2. ExamConsole형으로 만들어진 클래스
        ExamConsole console = ctx.getBean(ExamConsole.class);
		
        //3. 변수명과 한꺼번에 적음
//      ExamConsole console = ctx.getBean("console", ExamConsole.class);
		
//      Exam exam = new DiExam();
        //생성을 외부에서 해서 주입하는 것.
//      ExamConsole console =  new LineExamConsole(); //Grid냐 Line이냐에 따라 뒷부분만 바꾸면 됨.
//      ExamConsole console =  new GridExamConsole();
//      console.setExam();
        console.print();
    }
}

※ ApplicationContext 종류 : 지시서를 넘길 때, setting.xml의 위치를 알려주는 방법

-ClassPathXmlApplicationContext: Application의 루트(src)로부터 위치를 지정(보편적)

-AnnotationConfigApplicationContext: 추후 설명. 자바로 어노테이션 쓸 때,

-FileSystemXmlApplicationContext: 파일시스템의 경로(절대경로)를 이용해서 위치 지정
-XmlWebApplicationContext: web의 url통해 위치 지정

 

(4) 출력 결과

(1, 2, 3번 중 어느 방법을 써도)

total is 0, avg is 0.000000

 

(5) XML 에 값 설정하는 방법 2

(5-1) id 이름을 다르게 해서 사용

LineExamConsole()과 GridExamConsole()을 id를 다르게 해서 만들어 둠.

<?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="exam" class="com.di.entity.DiExam"/>
	
	<!-- new LineExamConsole(); 대신-->
	<bean id="console1" class="com.di.ui.LineExamConsole">
		<!-- exam 객체가 들어가야 함 -->
		<property name="exam" ref="exam"></property>
	</bean>
	
	<!--new GridExamConsole(); 대신. 필요에 따라 사용 -->
	<bean id="console2" class="com.di.ui.GridExamConsole">
		<!-- exam 객체가 들어가야 함 -->
		<property name="exam" ref="exam"></property>
	</bean>
	
	<!--이렇게 만들어진 것을 불러오는 뭔가가 있어야 하는데 >> App -->
</beans>

>> App.java에서 호출하는 법

package com.di;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import com.di.entity.DiExam;
import com.di.entity.Exam;
import com.di.ui.ExamConsole;
import com.di.ui.GridExamConsole;
import com.di.ui.LineExamConsole;

public class App {

	public static void main(String[] args) {
		                                                            //경로 설정
		ApplicationContext ctx = new ClassPathXmlApplicationContext("com/di/setting.xml");
		//1. id 적는 법. 리턴이 오브젝트형이라 타입캐스팅해줘야 함.
		ExamConsole console = (ExamConsole)ctx.getBean("console1");
//		ExamConsole console = (ExamConsole)ctx.getBean("console2");
		
		console.print();
	}
}

>> 출력 결과

console1번 total is 0, avg is 0.000000
console2번




┌──────────┬──────────┐
│ total    │ avg     │
├──────────┼──────────┤
│   0      │ 0.00     │
└──────────┴──────────┘

 

>> DI를 XML로 객체를 만들어서 주입하는 방법

IoC 컨테이너 사용. 코드는 안 바뀌었음. 맞는 것 선택해서 끼워넣는 것.


(6) 빈(Bean)에 실제 값을 넣는 방법

(6-0) 준비 작업

DiExam, GrideExamConsole, LineExamConsole 클래스에

필드를 전부 매개변수로 가지는 생성자, getter/setter, toString 작성

(호출하는)출력하는 App.java은 공통(변하지 않음)

package com.di;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import com.di.entity.DiExam;
import com.di.entity.Exam;
import com.di.ui.ExamConsole;
import com.di.ui.GridExamConsole;
import com.di.ui.LineExamConsole;

public class App {
	public static void main(String[] args) {
		                                                            //경로 설정
		ApplicationContext ctx = new ClassPathXmlApplicationContext("com/di/setting.xml");
		//1. id 적는 법. 리턴이 오브젝트형이라 타입캐스팅해줘야 함.
		ExamConsole console = (ExamConsole)ctx.getBean("console");
		console.print();
		
		//각각 어떤 값이 들어갔는데 toString 출력 - 오버라이딩 해놨던
		System.out.println(console.getExam()); //Exam의 toString 결과 출력
	}
}

 

(6-1) 필드 사용(접근자, 설정자) - getter/setter

<property> 사용

<?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="exam" class="com.di.entity.DiExam">
		<property name="kor" value="10"/> <!--setter 사용한 것-->
		<property name="eng" value="10"/>
		<property name="math" value="10"/> <!-- value 넣는 법 1 -->
		<property name="com">              <!-- value 넣는 법 2 -->
			<value>10</value>
		</property>
	</bean>

	<!--필요에 따라 사용.  -->
	<bean id="console" class="com.di.ui.GridExamConsole">
		<property name="exam" ref="exam1"/>
	</bean>
	
	<!--이렇게 만들어진 것을 불러오는 뭔가가 있어야 하는데... -->
</beans>

 

(6-2) 생성자 사용

<constructor-arg> 사용

<?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="exam1" class="com.di.entity.DiExam">
		<!-- 아무 것도 안 주고 네 개의 값, 생성자 순서대로 값 들어감. -->
		<!-- DiExam(int kor, int eng, int math, int com) -->
		<constructor-arg value="10"/> 
		<constructor-arg value="20"/>
		<constructor-arg value="30"/>
		<constructor-arg value="40"/>
	</bean>
	
	<!--필요에 따라 사용.  -->
	<bean id="console" class="com.di.ui.GridExamConsole">
		<property name="exam" ref="exam1"/>
	</bean>
	
	<!--이렇게 만들어진 것을 불러오는 뭔가가 있어야 하는데... -->
</beans>

>> 출력 결과

┌──────────┬──────────┐
│ total    │ avg      │
├──────────┼──────────┤
│ 100      │ 25.00    │
└──────────┴──────────┘
DiExam [kor=10, eng=20, math=30, com=40]

 

(6-3) 생성자 사용 2

<bean id="exam1" class="com.di.entity.DiExam">
	<!-- 아무 것도 안 주고 네 개의 값, ★생성자★ 순서대로 값 들어감. -->
	<!-- DiExam(int kor, int eng, int math, int com) -->
	<!-- 인덱스 번호(index)로 순서 설정 가능. -->
	<!-- 이름(name)으로 순서 설정 가능 -->
	<constructor-arg name="kor" value="10"/> 
	<constructor-arg name="com" value="20"/>
	<constructor-arg index="2" value="30"/>
	<constructor-arg index="1" value="40"/>		
</bean>

└kor 10, eng 40, math 30, com 20으로 설정된다. 

└값을 넣는 순서는 인덱스, 네임(name)으로 마음대로 할 수 있음. 그렇다고 출력 순서가 바뀌는 것은 아님)

└생성자 순서는 인덱스 0번부터 시작 - DiExam(int kor, int eng, int math, int com)

>> 출력 결과

┌──────────┬──────────┐
│ total    │ avg      │
├──────────┼──────────┤
│ 100      │ 25.00    │
└──────────┴──────────┘
DiExam [kor=10, eng=20, math=30, com=40]

 

(6-4) 간단하게 값을 넣는 방법

setting.xml의 namespace에서 [p] 체크

<!-- 간단하게 값 설정하는 방법 -->
<bean id="exam2" class="com.di.entity.DiExam" p:kor="1" p:eng="1" p:math="1"/>
	
<!--필요에 따라 사용.  -->
<bean id="console" class="com.di.ui.GridExamConsole">
    <!-- exam 객체가 들어가야 함 --><!-- 직접 값을 넣을 땐, value  ref 참조할 bean의 id -->
    <property name="exam" ref="exam2"/>
</bean>

>> 결과 출력

┌──────────┬──────────┐
│ total    │ avg      │
├──────────┼──────────┤
│   3      │ 0.75    │
└──────────┴──────────┘
DiExam [kor=1, eng=1, math=1, com=0]
 

 

(7) 컬렉션에 값 넣는 법

(7-0) DiExam에 필드 추가, 접근자/설정자(getter/setter) 추가, 투스트링 변경

private List<String> majors;

└값을 세팅할 때, XML에서 <list>로 넣어줌.

 

(7-1) 직접 값을 넣는 방법1

-App.java

package com.di;

import java.util.ArrayList;
import java.util.List;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import com.di.entity.DiExam;
import com.di.entity.Exam;
import com.di.ui.ExamConsole;

public class App {

	public static void main(String[] args) {
		                                                            //경로 설정
		ApplicationContext ctx = new ClassPathXmlApplicationContext("com/di/setting.xml");
		//1. id 적는 법. 리턴이 오브젝트형이라 타입캐스팅해줘야 함.
		ExamConsole console = (ExamConsole)ctx.getBean("console");
		console.print();
		
		//각각 어떤 값이 들어갔는데 toString 출력 - 오버라이딩 해놨던
		System.out.println(console.getExam()); //Exam의 toString 결과 출력
		
		//(4)
		DiExam exam = new DiExam(1,1,1,1);
		List<String> majors = new ArrayList<String>();
		majors.add("컴공");
		majors.add("수학");
		exam.setMajors(majors);
	}
}

└(4)번과 동일한 결과를 XML로 내는 법. XML에서 값을 설정하는 법.

 

-setting.xml

<!-- 4번 -->
<bean id="exam" class="com.di.entity.DiExam"><!-- 객체 생성-->
    <property name="kor" value="10"/>
    <property name="eng" value="10"/>
    <property name="math" value="10"/>
    <property name="com" value="10"/>
    <property name="majors">
        <list>
            <value>컴공</value>
            <value>수학</value>
        </list>
    </property>
</bean>
	
<!--필요에 따라 사용.  -->
<bean id="console" class="com.di.ui.GridExamConsole">
    <!-- exam 객체가 들어가야 함 --><!-- 직접 값을 넣을 땐, value  ref 참조할 bean의 id -->
    <property name="exam" ref="exam"/>
</bean>

>> 결과 출력

┌──────────┬──────────┐
│ total    │ avg      │
├──────────┼──────────┤
│  40      │ 10.00    │
└──────────┴──────────┘
DiExam [kor=10, eng=10, math=10, com=10, majors=[컴공, 수학]]

>> 빈에 실제 값을 넣어주는 것

 

(7-1) 직접 값을 넣는 방법2

-App.java

//(5) 컬렉션 객체 생성 : 아래의 작업을 하는 것.
List<Exam> exams = new ArrayList<Exam>();
exams.add(new DiExam(1, 1, 2, 3));
exams.add(new DiExam(1, 1, 2, 3));
		
for(Exam ex:exams) {
    System.out.println(ex);
}

위와 똑같은 결과를 XML을 사용해서 얻는 방법

                 <!-- class에는 객체를 만들 수 있는 것 적어야 함.-->
<bean id="exam5" class="java.util.ArrayList">
    <!-- 생성자로 만들 것. -->
    <constructor-arg>
        <list> <!-- 값 여러 개 넣을 거기 때문에 list 사용 -->
            <bean class="com.di.entity.DiExam" p:kor="1" p:eng="1" p:math="1"/>
            <!-- 이미 만들어진 빈 사용하려면 -->
            <ref bean="exam"/>
            <ref bean="exam1"/>
        </list>
    </constructor-arg>
</bean>

└위의 방법을 보다 간단하게 하는 법

setting.xml에서 네임스페이스 유틸(util) 체크

<util:list id="exam55" list-class="java.util.ArrayList">
    <bean class="com.di.entity.DiExam" p:kor="1" p:eng="1" p:math="1"/>
    <!-- 이미 만들어진 빈 사용하려면 -->
    <ref bean="exam"/>
    <ref bean="exam1"/>
</util:list>

>> 결과 출력

DiExam [kor=1, eng=1, math=1, com=0, majors=null]
DiExam [kor=10, eng=10, math=10, com=10, majors=[컴공, 수학]]
DiExam [kor=10, eng=40, math=30, com=20, majors=null]

-testDi01 Project >> com.di >> App.java

더보기
package com.di;

import java.util.ArrayList;
import java.util.List;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import com.di.entity.DiExam;
import com.di.entity.Exam;
import com.di.ui.ExamConsole;

public class App {

	public static void main(String[] args) {
		                                                            //경로 설정
		ApplicationContext ctx = new ClassPathXmlApplicationContext("com/di/setting.xml");
		//1. id 적는 법. 리턴이 오브젝트형이라 타입캐스팅해줘야 함.
//		ExamConsole console = (ExamConsole)ctx.getBean("console");
//		ExamConsole console = (ExamConsole)ctx.getBean("console");
		
//		console.print();
		
		//각각 어떤 값이 들어갔는데 toString 출력 - 오버라이딩 해놨던
//		System.out.println(console.getExam()); //Exam의 toString 결과 출력
		
		//(4)
//		DiExam exam = new DiExam(1,1,1,1);
//		List<String> majors = new ArrayList<String>();
//		majors.add("컴공");
//		majors.add("수학");
//		exam.setMajors(majors);
		
		//(5) 컬렉션 객체 생성 : 아래의 작업을 하는 것.
//		List<Exam> exams = new ArrayList<Exam>();
//		exams.add(new DiExam(1, 1, 2, 3));
//		exams.add(new DiExam(1, 1, 2, 3));
//		
//		for(Exam ex:exams) {
//			System.out.println(ex);
//		}
		//xml의 값을 출력?
		List<Exam> exams = (List<Exam>) ctx.getBean("exam5");
		for(Exam ex:exams) {
			System.out.println(ex);
		}
		
		//어레이리스트 생성할 때, 생성자에 컬렉션을 넣겠다.
//		List<Exam> exams1 = new ArrayList<Exam>();
	}
}

└오늘은 경로만 살려서 사용.


3. Annotation

xml에서 <bean>을 이용해 객체를 생성하고 값을 설정할 수 있었는데Annotaion의 @Autowired, @Qualifier, @Component를 이용해서 객체를 찾도록 하고 필드에 주입할 수 있다.(스프링에서 @Autowired만 붙인다고 되는 것이 아니라,xml파일에서 bean 객체를 설정할 때, @Autowired를 찾아서 세팅하라는 키워드를 넣어줘야 한다.)

<context:annotation-config/>

xml에서는 <bean>을 이용해 직접 값을 넣었는데 @Autowired를 사용하면 자동으로 객체를 넣어주는 것.

자동으로 객체를 연결해달라는 의미.

단, Spring에서 알아서 @Autowired를 찾는 것이 아니고 xml파일에서 bean객체를 설정할 때, @Autowired를 찾아서 세팅하라는 키워드를 넣어야 한다. <context:annotation-config/>

 

(1) 종류

@Autowired @Component("member1") @Qualifier("member1")
객체를 찾아라.
그 필드에 주입해라.
스프링 객체를 만들어라. 이름 붙이기.
member1이란 이름의 스프링 객체 생성
이름의 객체를 찾는다.
member1이란 이름의 스프링 객체 찾기

 

*참고로,

내가 직접 만들지 않은 것, 즉 스프링이 자체적으로 제공하는 것들은 Annotation하지 못함.

내가 직접 만든 것들만 Annotation할 수 있음.

ex) mvc만들 때, DAO, Action을 사용할 때 계속 new로 생성해줬는데 그럴 필요없이 @Autowired만 해주면 됐음.

 

*기존의 setting.xml 수정 >> setting02.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	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.3.xsd">
		
	<context:annotation-config/><!---★ Autowired를 찾아서 세팅해주라는 의미 -->
	<bean id="exam" class="com.di.entity.DiExam"><!-- 객체 생성-->
		<property name="kor" value="10"/>
		<property name="eng" value="10"/>
		<property name="math" value="10"/>
		<property name="com"><value>10</value></property>
		<property name="majors">
			<list>
				<value>컴공</value>
				<value>수학</value>
			</list>
		</property>
	</bean>
	
    <!--xml에서 값 세팅-->
<!--	<bean id="console" class="com.di.ui.LineMemberConsole">
			<property name="member" ref="member"/>
		</bean>-->
	
    <!--@Autowired사용할 때, property 생략-->
	<bean id="console" class="com.di.ui.GridExamConsole"/>
</beans>

Namespaces >> context 체크 후 <context> 입력

(*이때도 propety 지워야 하나 체크) >>  있어야 값을 찾음 / 없어도 됨. 

<bean>에서 값 입력하지 않고 @Autowired를 찾아서 세팅하라는 태그 입력했기 때문에.

 

>> LineExamConsole, GridExamConsole에 @Autowired 입력

@AutoWired : 만들어진 객체를 참조하는 것을 대신할 수 있음.

위치는 필드명 | setter | 매개변수가 있는 생성자(객체를 받는. 기본 생성자에는 사용하지 못함)

package com.di.ui;

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

import com.di.entity.Exam;

public class LineExamConsole implements ExamConsole {
	//★ 위치 1 @Autowired
    private Exam exam;
	
	//기본생성자
	//★ 위치 2 @Autowired
	public LineExamConsole() {}
    
	public LineExamConsole(Exam exam) {
		super();
		this.exam = exam;
	}
	public Exam getExam() {
		return exam;
	}
	//값을 set하는 함수
	// ★ 위치3 @Autowired
	public void setExam(Exam exam) {
		this.exam = exam;
	}

	//exam 내용 출력 함수
	@Override
	public void print() {
		System.out.printf("total is %d, avg is %f\n", exam.total(), exam.avg());
	}
}
//GridExamConsole
package com.di.ui;

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

import com.di.entity.Exam;

public class GridExamConsole implements ExamConsole {
	@Autowired
	private Exam exam;
	
	public void name() {
	}
	
	public Exam getExam() {
		return exam;
	}
	
	//기본생성자
	public GridExamConsole() {}

	// 값을 set하는 함수
	public void setExam(Exam exam) {
		this.exam = exam;
	}
	
	@Override 
	public void print() {
		System.out.println("┌──────────┬──────────┐");
		System.out.println("│ total    │ avg      │");
		System.out.println("├──────────┼──────────┤");
		System.out.printf("│ %3d      │ %3.2f    │\n", exam.total(), exam.avg());
		System.out.println("└──────────┴──────────┘");
	}
}

@Autowired 위치. set-위에 또는 디폴트 생성자에서는 사용할 수 없고 매개변수가 있는 생성자 위에 또는 필드명 위에. 제일 많이 위치하는 곳은 필드명 위.

 

-App.java에서 호출

package com.di;

import java.util.ArrayList;
import java.util.List;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import com.di.entity.DiExam;
import com.di.entity.Exam;
import com.di.ui.ExamConsole;

public class App {

	public static void main(String[] args) {
		                                                            //경로 설정
		ApplicationContext ctx = new ClassPathXmlApplicationContext("com/di/setting02.xml");
		ExamConsole console = (ExamConsole)ctx.getBean("console");
		console.print();
	}
}

>> 결과 출력 _ setting02.xml에서 활성화해놓은 것이 Grid이기 때문에 grid 출력됨

┌──────────┬──────────┐
│ total    │ avg      │
├──────────┼──────────┤
│  40      │ 10.00    │
└──────────┴──────────┘

 

(2) 동작방식 이해

@Autowired 동작방식 이해와 @Qualifier 사용

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns:context="http://www.springframework.org/schema/context"
	xmlns:p="http://www.springframework.org/schema/p"
	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.3.xsd">
	
    <!-- Autowired를 찾아서 세팅해주라는 의미 -->
	<context:annotation-config/> 
	<bean id="exam1" class="com.di.entity.DiExam"><!-- 객체 생성-->
		<property name="kor" value="10"/>
		<property name="eng" value="10"/>
		<property name="math" value="10"/>
		<property name="com"><value>10</value></property>
		<property name="majors">
			<list>
				<value>컴공</value>
				<value>수학</value>
			</list>
		</property>
	</bean>
	

	<bean id="console" class="com.di.ui.LineExamConsole">
		<!-- <property name="exam" ref="exam"/> -->
	</bean>
	
	<bean id="console" class="com.di.ui.GridExamConsole">
		<!-- <property name="exam" ref="exam"/> -->
	</bean>
</beans>

└데이터형으로 찾기 때문에 bean의 id가 달라도 찾을 수 있음.(이때, bean id = console에 <property> 없어야 함.)

지금 bean id = exam1인데, 소스 어디에서 exam1이 없지만! 단일이기 때문에 데이터형으로 찾아도 오류뜨지 않는다.

 

그러나,

xml에서 bean의 아이디가 동일한 게 없고, 여러 개 있을 때는 오류가 뜬다.

bean id가 exam1, exam2가 있지만 동일한 게 없음. 무엇을 선택해야 할지 알 수 없기 때문에.

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns:context="http://www.springframework.org/schema/context"
	xmlns:p="http://www.springframework.org/schema/p"
	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.3.xsd">
		
	<context:annotation-config/> <!-- Autowired를 찾아서 세팅해주라는 의미 -->
	<bean id="exam1" class="com.di.entity.DiExam"><!-- 객체 생성-->
		<property name="kor" value="10"/>
		<property name="eng" value="10"/>
		<property name="math" value="10"/>
		<property name="com"><value>10</value></property>
		<property name="majors">
			<list>
				<value>컴공</value>
				<value>수학</value>
			</list>
		</property>
	</bean>
	
	<bean id="exam2" class="com.di.entity.DiExam" p:kor="1" p:eng="1" p:math="1"/>	

	<bean id="console" class="com.di.ui.LineExamConsole"/>
	
	<bean id="console" class="com.di.ui.GridExamConsole"/>
</beans>

 

그럴 때는 Qualifier로 지정

package com.di.ui;

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

import com.di.entity.Exam;

public class GridExamConsole implements ExamConsole {
	@Autowired
	@Qualifier("exam2") //bean의 id가 exam2인 것을 쓰겠다.
	private Exam exam;
	
	public Exam getExam() {
		return exam;
	}
	
	//기본생성자
	public GridExamConsole() {}

	// 값을 set하는 함수
	public void setExam(Exam exam) {
		this.exam = exam;
	}
	
	@Override 
	public void print() {
		System.out.println("┌──────────┬──────────┐");
		System.out.println("│ total    │ avg      │");
		System.out.println("├──────────┼──────────┤");
		System.out.printf("│ %3d      │ %3.2f    │\n", exam.total(), exam.avg());
		System.out.println("└──────────┴──────────┘");
	}
}
package com.di.ui;

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

import com.di.entity.Exam;

public class GridExamConsole implements ExamConsole {
//	@Autowired(required = false)
	@Autowired
	@Qualifier("exam3")
	private Exam exam;
	
	public Exam getExam() {
		return exam;
	}
	
	//기본생성자
	public GridExamConsole() {}

	// 값을 set하는 함수
	public void setExam(Exam exam) {
		this.exam = exam;
	}
	
	@Override 
	public void print() {
		System.out.println("┌──────────┬──────────┐");
		System.out.println("│ total    │ avg      │");
		System.out.println("├──────────┼──────────┤");
		System.out.printf("│ %3d      │ %3.2f    │\n", exam.total(), exam.avg());
		System.out.println("└──────────┴──────────┘");
	}
}

└에러 뜸. 없으니까 출력문에서 에러가 뜸. exam 객체를 찾지 못하기 때문(xml에 exam 없음. 따라서 못참음)

public void print(){ ...exam.total().. } ← 여기서 exam을 못 찾기 때문.

여기서 exam은 bean id를 가리킨다.

 

package com.di.ui;

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

import com.di.entity.Exam;

public class GridExamConsole implements ExamConsole {
	@Autowired(required = false) //객체가 없다면 요구하지 않겠다.
//	@Autowired //기본이 true고 객체 요구
	@Qualifier("exam3")
	private Exam exam;
	
	public Exam getExam() {
		return exam;
	}
	
	//기본생성자
	public GridExamConsole() {}

	// 값을 set하는 함수
	public void setExam(Exam exam) {
		this.exam = exam;
	}
	
	@Override 
	public void print() {
		if(exam == null) {
			System.out.println("객체 생성되지 않음.");
		}else {
			System.out.println("┌──────────┬──────────┐");
			System.out.println("│ total    │ avg      │");
			System.out.println("├──────────┼──────────┤");
			System.out.printf("│ %3d      │ %3.2f    │\n", exam.total(), exam.avg()); //exam 객체 없다면 오류.
			System.out.println("└──────────┴──────────┘");
		}
	}
}

└출력문 수정. exam을 못 찾으면 객체 생성되지 않았다는 문구 뜨도록.

 

>> 출력 결과

객체 생성되지 않음.

 

(4) @Component

setting02.xml에서 Line과 Grid를 주석 처리. 그럼 App에서 어떻게 호출하는가?

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns:context="http://www.springframework.org/schema/context"
	xmlns:p="http://www.springframework.org/schema/p"
	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.3.xsd">
		
	<context:annotation-config/> <!-- Autowired를 찾아서 세팅해주라는 의미 -->
	<bean id="exam1" class="com.di.entity.DiExam"><!-- 객체 생성-->
		<property name="kor" value="10"/>
		<property name="eng" value="10"/>
		<property name="math" value="10"/>
		<property name="com"><value>10</value></property>
		<property name="majors">
			<list>
				<value>컴공</value>
				<value>수학</value>
			</list>
		</property>
	</bean>
	
	<bean id="exam2" class="com.di.entity.DiExam" p:kor="1" p:eng="1" p:math="1"/>	

	<!-- <bean id="console" class="com.di.ui.LineExamConsole"/> -->
	
	<!-- <bean id="console" class="com.di.ui.GridExamConsole"/> -->
</beans>

>> LineExamConsole과 GridExamConsole에 @Component로 이름 설정

package com.di.ui;

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

import com.di.entity.Exam;

@Component("console1") //★
public class LineExamConsole implements ExamConsole {
	@Autowired
	@Qualifier("exam1")
	private Exam exam;
	
	public void name() {
		
	}
	public Exam getExam() {
		return exam;
	}
	public LineExamConsole(Exam exam) {
		super();
		this.exam = exam;
	}

	//값을 set하는 함수
	public void setExam(Exam exam) {
		this.exam = exam;
	}

	//exam 내용 출력 함수
	@Override
	public void print() {
		System.out.printf("total is %d, avg is %f\n", exam.total(), exam.avg());
	}
}
package com.di.ui;

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

import com.di.entity.Exam;

@Component("console2") //★
public class GridExamConsole implements ExamConsole {
	@Autowired(required = false) //객체가 없다면 요구하지 않겠다.
//	@Autowired //기본이 true고 객체 요구
	@Qualifier("exam1")
	private Exam exam;
	
	public Exam getExam() {
		return exam;
	}
	
	//기본생성자
	public GridExamConsole() {}

	// 값을 set하는 함수
	public void setExam(Exam exam) {
		this.exam = exam;
	}
	
	@Override 
	public void print() {
		if(exam == null) {
			System.out.println("객체 생성되지 않음.");
		}else {
			System.out.println("┌──────────┬──────────┐");
			System.out.println("│ total    │ avg      │");
			System.out.println("├──────────┼──────────┤");
			System.out.printf("│ %3d      │ %3.2f    │\n", exam.total(), exam.avg()); //exam 객체 없다면 오류.
			System.out.println("└──────────┴──────────┘");
		}
	}
}

-setting02.xml

LineExamConsole과 GridExamConsole 경로 설정 : 패키지 이름 적어줌.

<context:component-scan base-package="com.di.ui"/>

 

(+)  xml 값 넣어주는 것도 안 함. 스캔할 것만 설정

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns:context="http://www.springframework.org/schema/context"
	xmlns:p="http://www.springframework.org/schema/p"
	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.3.xsd">
	<!-- 스캔하고 싶은 것 연결 -->		
    <context:component-scan base-package="com.di.ui, com.di.entity"/>
    <!-- <context:component-scan base-package="com.di.ui"/>LineExamConsole 위치/ 이걸 넣으면 annotation 쓸 필요 없음. -->
	<!-- <context:annotation-config/> --> <!-- Autowired를 찾아서 세팅해주라는 의미 -->
	<!-- <bean id="exam1" class="com.di.entity.DiExam">객체 생성
		<property name="kor" value="10"/>
		<property name="eng" value="10"/>
		<property name="math" value="10"/>
		<property name="com"><value>10</value></property>
		<property name="majors">
			<list>
				<value>컴공</value>
				<value>수학</value>
			</list>
		</property>
	</bean>
	
	<bean id="exam2" class="com.di.entity.DiExam" p:kor="1" p:eng="1" p:math="1"/> -->

<!--<bean id="console" class="com.di.ui.LineExamConsole" />
	
	<bean id="console" class="com.di.ui.GridExamConsole" /> -->

</beans>

└패키지 이름까지만 적으면 됨.

package com.di.entity;

import java.util.List;

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

@Component("exam1")
public class DiExam implements Exam {
	//값을 넣어주는 방법
	@Value("10")
	private int kor;
	@Value("20")
	private int eng;
	@Value("30")
	private int math;
	@Value("40")
	private int com;
	private List<String> majors;
	
	public List<String> getMajors() {
		return majors;
	}

	public void setMajors(List<String> majors) {
		this.majors = majors;
	}

	public DiExam() {
	}
	
	@Override
	public int total() {
		return kor+eng+math+com;
	}
	@Override
	public float avg() {
		return total()/4.0f; //4.0해줘서 실수로 결과 나옴.
	}
	public DiExam(int kor, int eng, int math, int com) {
		super();
		this.kor = kor;
		this.eng = eng;
		this.math = math;
		this.com = com;
	}

	public int getKor() {
		return kor;
	}

	public void setKor(int kor) {
		this.kor = kor;
	}

	public int getEng() {
		return eng;
	}

	public void setEng(int eng) {
		this.eng = eng;
	}

	public int getMath() {
		return math;
	}

	public void setMath(int math) {
		this.math = math;
	}

	public int getCom() {
		return com;
	}

	public void setCom(int com) {
		this.com = com;
	}

	@Override
	public String toString() {
		return "DiExam [kor=" + kor + ", eng=" + eng + ", math=" + math + ", com=" + com + ", majors=" + majors + "]";
	}	
}

-App.java

package com.di;

import java.util.ArrayList;
import java.util.List;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import com.di.entity.DiExam;
import com.di.entity.Exam;
import com.di.ui.ExamConsole;

public class App {

	public static void main(String[] args) {
		                                                            //경로 설정
		ApplicationContext ctx = new ClassPathXmlApplicationContext("com/di/setting02.xml");
		ExamConsole console = ctx.getBean("console1",ExamConsole.class);
//      ExamConsole console = ctx.getBean("console2",ExamConsole.class); //그리드 형태로 출력
		console.print();
	}
}

>> 출력 결과

total is 100, avg is 25.00

 

@Autowired : 객체찾아라. 그 필드에 주입해라.※ 요약 ※

@Component("") : 이름붙일 때, // 객체가 만들어진다. // 스프링 객체 만들어라.
@Qualifier("member1") : 이름 찾을 때,

위의 작업을 하기 위해서
xml 파일에서 
<context:component-scan base-package="com.di.ui, com.di.entity"/>
└<context:autonnation>은 안 적어도 됨.

*패키지를 폭넓게 잡으면(상위쪽 폴더일 경우) 다 뒤져서 찾음.
(구체적으로 필요한 것만 찾으라고 해주는 게 좋을 듯)

*xml에서 bean만들어서 해야 할 때, 클래스가 없을 때, 스프링에서 만들어준 것일 때.

 

(5) 특화된 @Component

세부적으로 객체화하고자 하는 클래스가 어떤 역할을 하는지 명시화.

controller service repository
요청을 받으면
떤일을 할지 정의하는 클래스
서비스 요구사항에 맞는 서비스 제공 DAO임을 나타내는 것

-서비스 : 비즈니스라는 걸 알려주는 것.

(*mvc : 뷰  -  컨트롤러  -(비즈니스 로직)-  모델  /  데이터베이스 처리하기 전에 ActionFactory 만들었던 것)

ex) '상품 구매'라는 하나의 작업에 따라, 포인트 지급, 재고 감소 등을 연관지어 묶는 것(?)

디비는 작업이 하나하나 하도록 되어 있음. 상품 구매, 포인트 지급, 재고 감소 작업이 각각 이루어짐.

 


4. Java Configuration

xml 코드를 자바 코드로 변경할 수 있음.

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns:context="http://www.springframework.org/schema/context"
	xmlns:p="http://www.springframework.org/schema/p"
	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.3.xsd">

	<context:component-scan base-package="com.di.ui, com.di.entity"/> <!-- 패키지 이름까지만 적으면 됨. -->

</beans>

xml에서 작업하지 않고 자바로 하기

 

(1) 클래스 생성 : com.di >> AppConfig.java

package com.di;

import java.util.ArrayList;
import java.util.List;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;

import com.di.entity.DiExam;
import com.di.entity.Exam;
import com.di.ui.ExamConsole;
import com.di.ui.GridExamConsole;
import com.di.ui.LineExamConsole;

@ComponentScan("com.di") //스캔할 때, - 1번
@Configuration //
public class AppConfig {
	//bean임을 알려주는 annotaion
	@Bean
	public Exam exam1() { //함수명이 exam이 id
		List<String> majors = new ArrayList<String>();
		DiExam exam1 = new DiExam(10,20,30,40);
		majors.add("컴공");
		majors.add("정보");
		exam1.setMajors(majors);
		return exam1;
	}
	
	//console - 2번
//	@Bean
//	public ExamConsole console1() {
//		return new LineExamConsole();
//	}
//	@Bean
//	public ExamConsole console2() {
//		return new GridExamConsole();
//	}
}

└2번 비활성화, 1번 활성화하면 값 제대로 출력됨.

 

>> 더욱 간력하게

package com.di;

import java.util.ArrayList;
import java.util.List;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;

import com.di.entity.DiExam;
import com.di.entity.Exam;
import com.di.ui.ExamConsole;
import com.di.ui.GridExamConsole;
import com.di.ui.LineExamConsole;

@ComponentScan({"com.di", "com.di.entity"})//스캔할 때,
@Configuration //
public class AppConfig {
	//bean임을 알려주는 annotaion
//	@Bean
//	public Exam exam1() { //함수명이 exam이 id
//		List<String> majors = new ArrayList<String>();
//		DiExam exam1 = new DiExam(10,20,30,40);
//		majors.add("컴공");
//		majors.add("정보");
//		exam1.setMajors(majors);
//		return exam1;
//	}
//	
//	//console
//	@Bean
//	public ExamConsole console1() {
//		return new LineExamConsole();
//	}
//	@Bean
//	public ExamConsole console2() {
//		return new GridExamConsole();
//	}
}

-App.java

package com.di;

import java.util.ArrayList;
import java.util.List;

import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import com.di.entity.DiExam;
import com.di.entity.Exam;
import com.di.ui.ExamConsole;

public class App {

	public static void main(String[] args) {
		
		AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(AppConfig.class);
		ExamConsole console = ctx.getBean("console1", ExamConsole.class);
		console.print();
	}
}

LineExamConsole, GridExamConsole에서 @Component 해줘야 함.

package com.di.ui;

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

import com.di.entity.Exam;

@Component("console1")
public class LineExamConsole implements ExamConsole {
	@Autowired
	@Qualifier("exam1")
	private Exam exam;
...
}
package com.di.ui;

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

import com.di.entity.Exam;

@Component("console2")
public class GridExamConsole implements ExamConsole {
	@Autowired(required = false) //객체가 없다면 요구하지 않겠다.
//	@Autowired //기본이 true고 객체 요구
	@Qualifier("exam1")
	private Exam exam;
...
}

└console1, console2는 exam1을 찾아서 값을 가져옴.(?)

package com.di.entity;

import java.util.List;

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

@Component("exam1")
public class DiExam implements Exam {
...
}

 

 

 

 

 

댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2025/05   »
1 2 3
4 5 6 7 8 9 10
11 12 13 14 15 16 17
18 19 20 21 22 23 24
25 26 27 28 29 30 31
글 보관함