2. Spring 의 이해 및 Nature maven 프로젝트 생성[DI 코드작성].pptx

Database 플러그인 설치

'Add...' 누르고

http://download.eclipse.org/releases/oxygen

'Database Development' 추가

> STS 재시작 (재시작 안 하면 show view에 안 나옴)

> Window > Show View > Other... > Data Source Explorer

 

 

 

POJO 익히기... 자바 프로젝트에 > 메이븐 > 스프링 바꾸기

1 ) 자바프로젝트 생성 'Extra 10.05.POJO'

mvc 말고 맨 처음 배운 그냥 '자바 프로젝트'로 생성

 

2 ) Maven Project로 변경

Group ID랑 Artifact ID는 공백이 들어가면 안 되네... (패키징은 jar로 한다... 아래 4에 있는 spring context에 패키징이 jar 인거 참고)

 

3) Sping Project Nature 추가하기

 

4) pom.xml에 Spring-context 추가하기

mvnrepository.com 여기서 'spring context' 검색

jar구나... 그리고 저 4.3.18은... 스프링 버전이라 한다. 바로 MVC 프로젝트로 만들 때는 마찬가지로 dependency에 가서 스프링 버전을 확인하면 된다.

이건 스프링 툴의 버전이고... 이클립스에 스프링 툴을 추가할 때는 이클립스 버전을 맞췄는데 얘는 안 맞춰도 되는 것 같다. 그냥 툴과 스프링 프레임워크는 그냥 별개인 듯.

pom.xml에 가서 version 아래 <dependencies></dependencies> (복수형이다.. cy 아니고 cies)를 만들고 그 안에 저 메이븐 dependency 복붙하기...

<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>POJO</groupId>
  <artifactId>POJO</artifactId>
  <version>0.0.1-SNAPSHOT</version>
  <!-- 여기다 추가 -->
  <build>
    <sourceDirectory>src</sourceDirectory>
    <plugins>
      <plugin>
        <artifactId>maven-compiler-plugin</artifactId>
        <version>3.8.0</version>
        <configuration>
          <release>11</release>
        </configuration>
      </plugin>
    </plugins>
  </build>
</project>
<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>POJO</groupId>
  <artifactId>POJO</artifactId>
  <version>0.0.1-SNAPSHOT</version>
  <dependencies>
  	<!-- https://mvnrepository.com/artifact/org.springframework/spring-context -->
	<dependency>
	    <groupId>org.springframework</groupId>
	    <artifactId>spring-context</artifactId>
	    <version>4.3.18.RELEASE</version>
	</dependency>
  </dependencies>
  <build>
    <sourceDirectory>src</sourceDirectory>
    <plugins>
      <plugin>
        <artifactId>maven-compiler-plugin</artifactId>
        <version>3.8.0</version>
        <configuration>
          <release>11</release>
        </configuration>
      </plugin>
    </plugins>
  </build>
</project>

 

3. POJO 및 DI 실습

5) 패키지, 클래스 추가하기

config, kopo.di.xml, test 패키지 3개 추가

kopo.di.xml 패키지 안에

Hello 클래스

package kopo.di.xml;

//import kopo.di.xml.Printer;

public class Hello {
	private String name;
	private Printer printer;
	
	public void setName(String name) {
		this.name = name;
	}
	
	public void setPrinter(Printer printer) {
		this.printer = printer;
	}
	
	public String sayHello() {
		return "Hello " + name;
	}
	
	public void print() {
		this.printer.print(sayHello());
	}
}

 

Printer 인터페이스

package kopo.di.xml;

public interface Printer {
	public void print(String message);

}

 

Printer 인터페이스를 상속하는 ConsolePrinter 클래스와 StringPrinter 클래스

ConsolePrinter

package kopo.di.xml;

public class ConsolePrinter implements Printer {
	
	@Override
	public void print(String message) {
		System.out.printf("ConsolePrinter call %s \n", message);
	}

}

 

StringPrinter

package kopo.di.xml;

public class StringPrinter implements Printer {

	@Override
	public void print(String message) {
		System.out.printf("StringPrinter call %s \n", message);		
	}
	
}

 

config 패키지 안에 beans.xml 추가 : 얘가 제어를 한다. MVC 패턴에서 홈컨트롤러에 해당하는 녀석 같다.

'Finish'누르지 말고 'Next >'

maven에 Spring-context를 추가했기 때문에 선택 가능하다.(?)

beans 선택하고 아래서 버전 선택

 

바로 'Finish'누른거

<?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>

'Next >' 누르고 버전 선택한거

<?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-4.3.xsd">


</beans>

 

< beans> </beans> 안에 추가한다.

<?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-4.3.xsd">
	
	<bean id="hello" class="kopo.di.xml.Hello">
		<property name="name" value="kopo!!!" />
		<property name="printer" ref="WhoAreYou" /> <!-- 얘는 아래 bean id="WhoAreYou"를 참조한다. -->
	</bean>
	
	<bean id="WhoAreYou" class="kopo.di.xml.StringPrinter" />
	<bean id="consolePrinter" class="kopo.di.xml.ConsolePrinter" />

</beans>

Beans에서 제어를 한다.  bean id 속성값이 매핑됨(예 : hello 호출 시 name에 kopo 값이 설정됨???)

참고 : beans.xml에는 아래와 같읕 탭이 있다. 여기서 Namespaces에서 beans에 꼭 체크가 되어 있어야 한다.

이 bean은 MVC 패턴에서 Controller와 비슷한 역할을 한다.

 

test 패캐지 안에 HelloBeanTest 클래스와 그 안에 메인 메소드를 생성

package test;

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

import kopo.di.xml.Hello;
import kopo.di.xml.Printer;

package test;

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

import kopo.di.xml.Hello;
import kopo.di.xml.Printer;

public class HelloBeanTest {
	public static void main(String[] args) {
		// 1. IoC 컨테이너 생성
		ApplicationContext context = new GenericXmlApplicationContext("config/beans.xml");
		
		// 2. 위 1번에서 만든 context 변수(config/beans.xml를 가짐)에서 "hello"라는 id를 가져온다(getBean메소드).
		// 그리고 그 가져온 값을 Hello 자료형의 hello라는 변수에 담는다.
		Hello hello = (Hello)context.getBean("hello");
		// 즉 아래 값이 담겨있다.
		// <bean id="hello" class="kopo.di.xml.Hello">
		// 	  <property name="name" value="kopo!!!" />
		// 	  <property name="printer" ref="stringPrinter" />
		// </bean>
		// 이걸 해석하면 id는 헬로(getBean으로 가져올 때 사용), 그리고 클래스는 kopo.di.xml 패키지 안에 Hello라는 자바 클래스.
		// property는 이 Hello 자바클래스에 생성자처럼 작동(정확히는 setter를 이용해 값을 대입),
		// name에 값으로 문자열(value) "kopo!!!"를 넣고, printer는 참조(bean id) "WhoAreYou"를 넣는데,
		// 이 "WhoAreYou"의 bean id는 아래 또 다른 bean에 의해 kopo.di.xml.SringPrinter로 정의되어있다.
		
		// hello의 sayHello 메소드를 실행한다. 그러면 Hello + name(<- 여기에 kopo!!! 가 대입되어있다.)를 return하고 그것을 출력한다.
		System.out.println(hello.sayHello());
		
		// 얘는 hello의 print() 메소드를 실행하므로 this.printer(sayHello())를 실행한다.
		// 즉, printer는 bean id="WhoAreYou"에 의해 kopo.di.xml.StringPrinter를 참조하므로 StringPrinter call + message (<- sayHello())를 출력
		hello.print();
		
		System.out.println();
		
		// Printer 자료형의 printer 변수에 context에서 "conslePrinter"를 id로 갖는 bean을 찾아 넣는다. (3가지 방법으로 구현. 그에 따른 print메소드 실행은 아래 2가지로 나뉨.)
		Printer printer = context.getBean("consolePrinter", Printer.class);	// 좌변이 Printer라서 우변의 ConsolePrinter를 Printer.class라는 자료형으로 받겠다고 미리 이야기.(제네릭?)
//		Printer printer = (Printer) context.getBean("consolePrinter");	// 좌변이 Printer라서 우변의 ConsolePrinter를 Printer로 형변환.
//		Object printer = context.getBean("consolePrinter");	// 우변이 ConsolePrinter라서 뭐든 받을 수 있는 최상위 객체 부모인 Object 객체 자체로 받음.
		
		
		// printer 변수(Printer 자료형으로 형변환 된 ConsolePrinter 객체)의 print(String message) 메소드를 실행.
		// ConsolePrinter call + message (<- "GOOD~~~~~") 출력.
		printer.print("GOOD~~~~~");
		
		// 위에서 좌변에서 우변의 ConsolePrinter 객체를 Object로 받아서, printer라는 Object 변수를 Printer로 형변환한다. 그 다음 Printer 자료형의 printer 메소드 실행 가능.
//		((Printer) printer).print("GOOD~~~~~");
		
		// 즉, Hello hello = (Hello)context.getBean("hello"); 이것과 같은 얘기다.
		Hello hello2 = context.getBean("hello", Hello.class);
		
		System.out.println();
		
		// hello와 hello2는 불러온 방식만 다르지 같은 값을 가진 2개의 인스턴스인 것처럼 보인다. 데이터는 같고 메모리 주소는 다른...		
		// 하지만 둘의 해시코드를 확인해보면 동일한 값 하나를 둘이 동시에 참조한다는 것을 알 수 있다.
		System.out.printf("\n hello.hashCode()  : %s \n hello2.hashCode() : %s", hello.hashCode(), hello2.hashCode());
		System.out.printf("\n hello == hello2, they are singleton. Is it true? >> %s!! \n", hello.hashCode() == hello2.hashCode());
	
	}
}





결과 :

Hello kopo!!!		<- System.out.println(hello.sayHello()); 에 의해 출력
StringPrinter call Hello kopo!!! 		<- hello.print(); 에 의해 출력

ConsolePrinter call GOOD~~~~~ 		<- printer.print("GOOD~~~~~"); 에 의해 출력

hello == hello2, they are singleton. Is it true? >> true!!		<- System.out.printf("hello == hello2, they are singleton. Is it true? >> %s!!", hello == hello2); 에 의해 출력

 

말 그대로 메인메소드. 얘가 실행을 한다. 그러면 bean이 Controller처럼 작동한다.

 

property에 value와 ref는 어떻게 다를까?

<bean id="hello" class="kopo.di.xml.Hello">
  <property name="name" value="kopo!!!" />
  <property name="printer" value="StringPrinter" />
</bean>

이렇게 하면 에러가 난다. property는 Hello.java 클래스를 인스턴스화 하고 name이란 값에 setter를 이용해 문자열(value) "kopo!!!"를 대입한다. 마찬가지로 printer라는 값에 name과 똑같이 문자열(value) "StringPrinter"를 대입하면?

public void setPrinter(Printer printer) {
	this.printer = printer;
}

얘가 this.printer = "StringPrinter"가 되는거다. 즉, 그냥 문자열이 들어감.

그래서 printer라는 property에는 ref를 써서 StringPrinter를 참조하도록 넣어야한다.

따라서, 이 때 value가 아닌 ref를 쓰게 되면 이것은 문자열이 아닌 bean id를 찾도록 한다. 즉, bean id = "StringPrinter"를 찾는 것이다. 따라서 아래와 같이 쓸 수 있다.

<bean id="hello" class="kopo.di.xml.Hello">
  <property name="name" value="kopo!!!" />
  <property name="printer" value="WhoAreYou" />
</bean>

<bean id="WhoAreYou" class="kopo.di.xml.StringPrinter" />

 

마찬가지로 아래쪽 Printer를 보면 좌우변의 자료형만 잘 맞춰주면 어떤 방법을 사용하던 무관하다.

// 방법 1. 좌변이 Printer 타입이니 우변을 Printer.class 타입으로 받겠다고 이야기한다.(제네릭?)
Printer printer = context.getBean("consolePrinter", Printer.class);
printer.print("GOOD~~~~~");

결과 : 
ConsolePrinter call GOOD~~~~~


// 방법 2. 좌변이 Printer 타입인데 우변이 ConsolePrinter 타입이니 Printer로 캐스팅
Printer printer = (Printer) context.getBean("consolePrinter");
printer.print("GOOD~~~~~");

결과 : 
ConsolePrinter call GOOD~~~~~


// 방법 3. 우변에 뭐가 올 지 모르거나 뭐든 다 받기 위해 좌변을 Object(객체의 최상위 부모)로 받음.
Object printer = context.getBean("consolePrinter");
// 대신 Object에는 print(String) 메소드가 없어서 Object 타입의 printer 변수를 Printer 타입으로 캐스팅해서 사용한다.
((Printer) printer).print("GOOD~~~~~");

결과 :
ConsolePrinter call GOOD~~~~~

 

그래서 싱글턴이란??

소프트웨어 디자인 패턴에서 싱글턴 패턴(Singleton pattern)을 따르는 클래스는, 생성자가 여러 차례 호출되더라도 실제로 생성되는 객체는 하나이고 최초 생성 이후에 호출된 생성자는 최초의 생성자가 생성한 객체를 리턴한다. 이와 같은 디자인 유형을 싱글턴 패턴이라고 한다. 주로 공통된 객체를 여러개 생성해서 사용하는 DBCP(DataBase Connection Pool)와 같은 상황에서 많이 사용된다.

 

 

Tag.

싱글톤, 싱글톤 패턴, 싱글톤패턴, 싱글턴, 싱글턴 패턴, 싱글턴패턴, singleton, Singleton, singleton pattern, Singleton pattern, Singleton Pattern, bean, beans, 자바 빈, 자바 빈즈, java bean, java baenas, Java bean, Java Bean

+ Recent posts