■ 이론
### sts3로 spring legacy project 작성하기
(이클립스 버전에서 플로그인해도 spring legacy project가 안 만들어지는 경우에도 유용함)
sts4는 기본이 spring boot 전용, legacy x
(그러므로 필요시 Spring Tolls 3 Add-On for Spring Tools4를 플러그인은 가능)
즉, 우리는 sts3로 spring legacy project 작성(또는 이클립스 2020-09)로도 작성
sts4를 다운받아 aka sts4를 플러그인하면서 (필요시 st3 add On st4 플러그인)
spring boot, spring cloud
spring legacy project(maven project)
(1) 이클립스 + spring을 plug-in
(2) sts3(spring tool suite3)
(3) sts4 + Spring Tools 3 Add-On for Spring Tools4
-------------------------------------------------------------------------------------------------
spring boot
(1) sts4
(2) 이클립스 + aka sts4
spring cloud
intelij
-------------------------------------------------------------------------------------------------
JAVA EE(Java Enterprise Edition) vs Spring
JavaEE - 웹 기술인 JSP, Servlet, 분산처리 기술인 EJB(Enterprise Java Beans) 기술
이때 EJB 작성 후 배포시 통일되는 기준없이 xml을 만들어 각각 배포하는 문제 발생
(참고 : 엔터프라이즈 - 기업의 업무처리를 위한 것)
그래서 spring이 대두됨
spring framework vs api(javascript)
지도인 경우 html5-javascript api
rest api
spring 별명 = spring servlet
- 스프링이란?
* 별명은 spring servlet
* 쉽고 효율적인 JavaEE 개발을 위한 framework
* 개발자 - Rod Johnson
* 이전 spring 사이트 영문정의
Spring is the most popular application development framework for enterprise JAVA.
Millions of developers use Spring to create high performing, easy testable, reusable code without any lock-in
- 스프링의 특징
* lightweight(경량)급 프레임워크
* 무거운 EJB의 해결책
* 엔터프라이즈 시스템에서 요구하는 분산처리, 확장성, 안정성 등을 해결
* POJO를 베이스로 하는 엔터프라이즈 개발 프레임워크로 재사용성이 좋다(jsp, servlet에서는 pojo x)
<자바의 변천사>
처음에 java => jsp(html + jsp) => servlet(자바, http)
(참고) POJO : Plain Old Java Object로 자바가 중심이고 자바는 다른 것에 종속되지 않는다.
(다른? 클래스를? 상속받아서? 만들어야? 하는? 클래스가? 아니다)?
(참고) 전자정부 표준 프레임 워크
(참고) 토비의 스프링
## 스프링 작성을 위한 준비
1) non-maven으로 작성하기
eclipse의 Dynamic WEB project의 lib방에
스프링 .jar 파일을 붙여넣기 위해 jar 파일을 직접 다운로드 예) ojdbc8.jar
<spring에서 제공하는 jar 파일>
spring-beans-4.17.RELEASE.jar
https://repo.spring.io/ui/native/libs-release/org/springframework/spring/4.1.7.RELEASE/spring-framework-4.1.7.RELEASE-dist.zip
<mvnrepository>
### pom.xml이란
* pom(Project Object Model)
* 메이븐 프로젝트 설정파일 (xml)
(참고) non-maven (직접 jar를 web-inf-lib에 추가하는 방식)
(예)
<dependencies>
<dependency> (라이브러리 하나씩 기록, 빌드시 저장소에서 라이브러리를 다운로드함)
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId> -- 모듈 이름(아티팩트 이름)
<version>${org.springframework-version}</version> --> 버전
</dependency>
</dependencies>
--> 위의 의미는 classpath에
spring-context- 버전.Release.jar 파일이 추가되는 것을 의미함
(참고)
<version>${org.springframework-version}</version> 대신에
<version>4.1.7</version> 등으로도 사용 가능하다.
하지만 가능한 ${org.springframework-version} 형식을 사용.
- What is Maven?
* maven은 "라이브러리 다운로드 관리자"이다
즉, pom.xml에 선언된 라이브러리를 파악하여 중앙저장소에서 로컬 저장소로 라이브러리를 다운한다.
(jetbrains사의 Intellij(인텔리제이)는 다름) - 마치 직접 입력하는 형식과 유사
* 로컬저장소의 위치는 기본적으로 "사용자/.m2/repository"이고
프로젝트의 library 아래 maven dependency 아래에
나오는 경로를 보아 로컬 저장소 위치를 알 수 있다.
Maven Repository 창 나타내기
Windows - Show View - Other - Maven - Maven Repository를 클릭하면
로컬, 중앙저장소경로가 보임
DI (Dependency Injection, 의존성 주입)
spring의 bean : 스프링에서 객체생성시 bean 객체라고 표현함
표현방법은 <bean id="bangkaBean1" class="bangka.Bangka1" />이며
- id에는 객체명을 쓰고 class에는 패키지명.클래스명을 쓴다
이는 다음과 같은 의미이다.
Bangka1 bangkaBean1 = new Bangka1() // do you remember "userBean"
태그에 보면 /> 닫는 부분이 존재 : xml 안으로 들어간다.
xml에 안에 객체를 넣고 필요할 때 가져다 쓴다.
#############################################
## dynamic으로 작성시 할 일 ###
# 처음 프로젝트 작성시 JAVA EE로 할 거냐는 창이 뜨면 YES
#(1) 아래 JFrog는 로그인 해야 하므로
로그인 하기 싫으면 mvnrepository에서 가져오면 된다.
#(2) ### 액박시 2군데를 jdk 11로 맞춘다.
1) buid path로 가서 상단 library 탭에서 jdk 17 -> 11로
2) build path로 가서 project facet의 java 부분을 17 -> 11로
#(3) lib 방에 .jar 넣기
Dynamic web project의 lib 방에
스프링 .jar(.class 파일의 집합) (rt.jar 참고) 파일을 복붙
<spring에서 제공하는 jar 파일 예>
- 생략
### .xml 만들기
(1) src/main/java 에 마우스우클릭하면 파일 - new - .xml 만들면 만들어 지지만
or
(2) spring bean configuration file(스프링 빈 설정 파일)로 작성
(2-1) applicationContext.xml 작성
src(src/main/java) - 마우스우클릭 - new - other 가면
spring 폴더 안에 spring bean configuration file...
(이때 src/main.java인 경우 위치가 java로 잡히면 ok)
- applicationContext.xml 이름 하나 주고 - (next) - finish
### DI
Dependency Injection으로 "의존성 주입"이라고 함
즉, DI란 Dependency(의존)을 외부에서 받는 것을 의미하며
스프링에서는 외부의 역할인 IoC Container에 의해 스프링 객체인 bean객체가 injection(주입)된다.
###. 결합도 및 응집도
응집도 : 모듈 내부 내용끼리의 관련 정도(sort하고 결과 출력이 같은 모듈 안에 있다면 응집도 high)
결합도 : 모듈과 모듈 사이의 관련 정도 (sort한 결과를 다른 모듈에서 받아서 출력한 경우 결합도 high)
응집도 high, 결합도 low가 좋음
###. IoC란
Inversion of Control로 "제어의 역전"을 의미함
즉, 객체의 생성, 제어를 개발자가 하는 것이 아니라 IoC 엔진인
Spring Container(IoC Container, Bean Factory, ApplicationContext)가 대신 해줌.
(물론 구현은 개발자가 하지만 스프링은 프레임워크이므로
프레임워크의 특징대로 진행 자체는 스프링 프레임워크에 의해 이루어짐)
(참고) Bean Factory (bean관리, getBean(), interface)
↑
ApplicationContext (interface)
■ 기본 실습
dynamic web project에서 src/main.java에 nalpkg1 생성.
다음의 2개의 클래스 파일 만든다.
□ Nalja.java
package nalpkg1;
import java.util.Date;
public class Nalja {
public void nalja() { // 메소드
Date d1 = new Date();
System.out.println(d1);
}
}
□ NalssiOndo.java
package nalpkg1;
public class NalssiOndo {
public void nalssiondo() { // 메소드
System.out.println("sunny and 23");
}
}
그리고 난 후 hellopkg1 생성 - Hello.java 생성
□ Hello.java
package hellopkg1;
import nalpkg1.Nalja;
import nalpkg1.NalssiOndo;
public class Hello {
// Dynamic web + java
public static void main(String[] args) {
// 자바이므로 실행시 run application
// main()에서 다른 패키지에 있는 클래스의 메소드를 call 하려면
// 여기서 해당 객체를 만들어서 사용하는 것이 기본 방법
Nalja b1 = new Nalja(); // new를 사용하여 클래스의 객체 생성
b1.nalja(); // Nalja.java에 있는 nalja() 메소드 call
NalssiOndo b2 = new NalssiOndo(); // new
b2.nalssiondo(); // NalssiOndo.java에 있는 nalssiondo() 메소드 call
// 결합도, 응집도의 관점
}
}
참고, lib 폴더엔 다음과 같은 것들이 들어간다.
■ 기본실습 2 (bean, applicationContext)
dynamic web project에서 src/main.java에 nalpkg1 생성.
다음의 2개의 클래스 파일 만든다.
□ Nalja.java
package nalpkg1;
import java.util.Date;
public class Nalja {
public void nalja() { // 메소드
Date d1 = new Date();
System.out.println(d1);
}
}
□ NalssiOndo.java
package nalpkg1;
public class NalssiOndo {
public void nalssiondo() { // 메소드
System.out.println("sunny and 23");
}
}
□ appcont.xml
다음과 같이 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">
<!--
지금 나는 applicationContext.xml
dynamic non-maven 에서는 xml 위치가 src 아래
spring legacy-maven에서는 xml 위치가 resources 아래
-->
<!--
<환경설정 방식 3가지> xml, annotation, java
xml에 다음처럼 코딩하면 객체 만들어짐
-->
<!-- id = 다음은 객체명 패키지명.클래스명 -->
<bean id="nalbean1" class="nalpkg1.Nalja"/>
<!--
<jsp:useBean>
위의 내뇽은 다음 내용을 의미
package nalpkg;
Nalja nalbean1 = new Nalja();
-->
<bean id="nalbean2" class="nalpkg1.NalssiOndo"/>
</beans>
□ Hello.java
package hellopkg1;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import nalpkg1.Nalja;
import nalpkg1.NalssiOndo;
public class Hello {
// 이미 oop의 정의(class), 생성(new는 xml에서)은 작성했으므로
// oop애서 3단계인 "사용"을 해보자
// 객체.속성 = 값 // 객체.메소드() // 객체.속성
// POJO
public static void main(String[] args) {
// 스프링은 pojo를 기반
// bean : spring이 관리하는 인스턴스(객체)
// ApplicationContext = bean container = bean을 관리
// BeanFactory가 ApplicationContext 인터페이스의 상위 인터페이스
ApplicationContext ac1 = new ClassPathXmlApplicationContext("appcont.xml");
// ctrl + shift + o : import 선택할 때 apache x, springframework o
// (예) import org.springframework.context.ApplicationContext;
// ==> classpath(src/main/java, src/main/resource)에서 xml(or java source)을 읽어와
// bean 설정 메타정보(BeanDefinition) 등을 얻어 ApplicationContext 객체(인스턴스)를 생성
// (메타정보는 "1 <bean> 1 정보" 이며 (or 1 @bean 1 정보)
// 스프링컨테이너는 bean id, 클래스이름 같은 메타정보를 통해 스프릴ㅇ bean을 생성함
// 그러니까 클래스에 대한 new가 여기서 만드는 게 아니다.
// 아래에서도 ctrl + shift + o 활용
// (1) // xml에서 new
Nalja b1 = ac1.getBean("nalbean1", Nalja.class);
// Bean 객체 생성 및 초기화 제거 등을 관리함
// 객체.메소드() with type // (2)번 사용보다는 (1)번 기법 사용을 권장
// (2) Nalja b1 = (Nalja)ac1.getBean("nalbean1"); // 객체.메소드
b1.nalja();
// #### getBean() 메소드 찾아보기
// getBean() 메소드 : Bean 객체 생성 및 초기화 제거 등을 관리함
// web app libraries를 찾아가서
// spring-beans-...jar - org.springframework.beans.factory
// - BeanFactory.class - BeanFactory - getBean()
// 앞에 (2)번째 방법으로 해본 것
NalssiOndo b2 = (NalssiOndo)ac1.getBean("nalbean2");
b2.nalssiondo();
}
}
■ 기본실습 3 (섭씨, 화씨)
Q) NalssiOndo 클래스의 bean 객체를 만들 때 초기치로 온도값을 23도로 설정하고
섭씨를 화씨로 변환하여 출력하는 프로그램을 작성하시오
단)
(1) constructor injection (constructor DI) 기법 중 c:ondp = 문법을 사용하시오
(2) 섭씨를 화씨로 변환해주는 메소드를 추가하시오
(3) 위 메소드를 바로 호출하여 30도를 사용하여 결과를 출력하는 방법과
객체 변수를 활용하여 50도를 변환 출력하는 2가지 방법으로 작성하시오.
□ nalpkg
* Nalja.java
package nalpkg1;
import java.util.Date;
public class Nalja {
public void nalja() { // 메소드
Date d1 = new Date();
System.out.println(d1);
}
}
* NalssiOndo.java
package nalpkg1;
public class NalssiOndo {
private int ondo;
public void setOndo(int ondo) {
this.ondo = ondo;
}
public void nalssiondo() { // 메소드
System.out.println("sunny and " + ondo + "도 온도");
}
public void CtoFMethod(int ondo) {
System.out.println(ondo * 1.8 + 32);
}
}
□ ctofpkg
* CtoFClass.java
package ctofpkg;
import nalpkg1.NalssiOndo;
public class CtoFClass {
// 클래스명 객체변수
private NalssiOndo nalssiondo; // 속성, 필드
// nalssiondo는
// <bean id="nalbean2" class="nalpkg.NalssiOndo" 관련 nalbean2 bean 객체를 전달받음>
// getter, setter, 생성자
public CtoFClass(NalssiOndo nalssiondo) { // 생성자 // 객체를 초기치로 받음.
this.nalssiondo = nalssiondo;
}
// getter, setter
public NalssiOndo getNalssiondo() {
return nalssiondo;
}
public void setNalssiondo(NalssiOndo nalssiondo) {
this.nalssiondo = nalssiondo;
}
} // CtoFClass-end
□ appcont.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:p="http://www.springframework.org/schema/p"
xmlns:c="http://www.springframework.org/schema/c"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<!--
지금 나는 applicationContext.xml
-->
<!--
xml에서 bean 객체를 작성해서 IOC 기법으로 bean 객체를 DI + 초기치
기본 자바라면 setter, construction을 사용
-->
<!-- 날짜는 초기치 없이 객체만 생성 -->
<bean id="nalbean1" class="nalpkg1.Nalja"/>
<!--
온도 초기치 x, 객체 생성
<bean id="nalbean2" class="nalpkg1.NalssiOndo"/>
-->
<!--
Sawon sawon1 = new Sawon();
useBean으로 바꾸면
<jsp:useBean id="sawon1" class="sawonpkg.Sawon"/>
-->
<!--
sawon1.setIrum("hong")
<jsp:setProperty name="sawon1" property="irum" value="hong"/>
-->
<!--
그렇다면 spring에서는
위의 내용에 초기치 문법을 추가 하자
즉, 아래는 nalbean2객체.setOndo(23) 메소드 개념
-->
<!--
setter 사용시
<bean id="nalbean2" class="nalpkg1.NalssiOndo">
<property name="ondo" value="23"/>
</bean>
줄여쓰기는
setTel("010-3333-5555") 대신에 p:tel="010-3333-5555"
예) <bean id="sawonBean" class="sawinpkg.SawonClass"
p:name="홍길동" p:tel="010-8888-7777">
-->
<bean id="nalbean2" class="nalpkg1.NalssiOndo" p:ondo="23">
</bean>
<!--
p:를 사용하면 에러가 뜨는데
해결하려면
xml 파일의 맨 아래 탭을 보면 Namespaces 탭이 보인다.
해당 탭에서 p를 체크해야 한다. 그러면 xml 파일의 상단에 namespace p가 보인다.
(참고) 만일 하단에 napespaces 탭이 안 보일 경우
# 1st 작업
.xml - 마우스 우클릭 - open with - spring configure editor 선택
- namespaces 탭 보인다
# 2nd (1st가 안 되면 다음 2nd 작업 추가한 후 1st 다시 시도, sts3에서는 사용x)
<이클립스 only>에서 help - eclipse Marketplace
find - sts - 2개 install 함
1. spring tool 4(aka...sts4)
2. spring tool 3 add on for st 4...
-->
<!--
여기서 초기치를 생성자로 넣고자 할 때는
<constructor-arg name="ondo" value="23"/>
<bean id="nalbean2" class="nalpkg1.NalssiOndo">
<constructor-arg name="ondo" value="23"/>
</bean>
생성자는 setter를 삭제하고, 인자가 있는 생성자를 만들어서 사용한다.
<bean id="nalbean2" class="nalpkg1.NalssiOndo" c:ondo="23">
-->
<!--
이제는 객체를 넘겨줘야 함
섭씨온도를 화씨로 변환하는 문법이 필요한데
따라서 온도가 포함되어 있는 객체를 당연히 넘겨줘야 함
그것은 바로 nalbean2 객체
<bean id="ctofbean3" class="ctofpkg.CtoFClass">
그리고 여기에 앞에서 나온 setter, 생성자 기법으로 객체 초기치를 넘겨주면 된다.
-->
<!-- ================= 생성자 기법으로 해보자 ================= -->
<!-- <bean id="ctofbean3" class="ctofpkg.CtoFClass">
<constructor-arg name="nalssiondo" ref="nalbean2"/>
setNalssiondo(nalbean2)
=> ctofpkg 아래 CtoFClass에 있는 nalssiondo 객체변수에 nalbean2 bean 객체가 들어감
</bean> -->
<bean id="ctofbean3" class="ctofpkg.CtoFClass" c:nalssiondo-ref="nalbean2"></bean>
</beans>
□ hellopkg1
* Hello.java
package hellopkg1;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import ctofpkg.CtoFClass;
import nalpkg1.Nalja;
import nalpkg1.NalssiOndo;
public class Hello {
public static void main(String[] args) {
ApplicationContext ac1 = new ClassPathXmlApplicationContext("appcont.xml");
Nalja b1 = (Nalja)ac1.getBean("nalbean1");
b1.nalja();
NalssiOndo b2 = (NalssiOndo)ac1.getBean("nalbean2");
b2.nalssiondo();
// 객체변수를 전달 ==> 객체를 넘김
// 만약
// SawonClass sawon1 = new SawonClass();
// DI 기법으로 넘겨주는데 sawon1을 넘기라는 것
//------------------------------------------------------------
// 섭씨온도 30도를 생성자 초기치 기법으로 넣어서 화씨온도를 구하는 형식
b2.CtoFMethod(30); // NalssiOndo.java에 있는 메소드로 섭씨를 화씨로 변경
//------------------------------------------------------------
CtoFClass cf1 = ac1.getBean("ctofbean3", CtoFClass.class);
// nalbean2 객체가 생성자에 의해 전달받아 nalssiondo 객체 변수에 들어감
cf1.getNalssiondo().CtoFMethod(50); //cf1.nalbean2객체.CtoFMethod(50)을 의미함.
// b2.CtoFMethod(50)
// xml에서 nalBean2 객체를 보내는데 객체변수를 통해서 넘어온 것. 여기에 초기치 50을 넣어주면
// ctof 함수를 찾아가서 계산이 이루어지면서 섭씨온도를 출력
}
}
■ 기본실습 3 (@Value)
□ appcont.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:p="http://www.springframework.org/schema/p"
xmlns:c="http://www.springframework.org/schema/c"
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-3.1.xsd">
<!--
지금 나는 applicationContext.xml
-->
<context:annotation-config /> <!-- bean annotation을 활성화시키는 역할 -->
<bean id="nalbean1" class="nalpkg1.Nalja"/>
<bean id="nalbean2" class="nalpkg1.NalssiOndo"/>
</beans>
□ nalpkg1
* Nalja.java
package nalpkg1;
import java.util.Date;
public class Nalja {
public void nalja() { // 메소드
Date d1 = new Date();
System.out.println(d1);
}
}
□ NalssiOndo.java
package nalpkg1;
import org.springframework.beans.factory.annotation.Value;
public class NalssiOndo {
// setter x, or constructor x, xml 초기치 (c: p: x) 없어짐
// 대신 xml 파일에 <context: annotation-config/>
@Value("23") // 초기치
private int ondo;
// 처음에는 만들고 실행, 두 번째는 setter 주석달고 실행
// public void setOndo(int ondo) {
// this.ondo = ondo;
// }
public void nalssiondo() { // 메소드
System.out.println("sunny and " + ondo + "도 온도");
}
}
□ hellopkg1
* Hello.java
package hellopkg1;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import nalpkg1.Nalja;
import nalpkg1.NalssiOndo;
public class Hello {
public static void main(String[] args) {
ApplicationContext ac1 = new ClassPathXmlApplicationContext("appcont.xml");
Nalja b1 = (Nalja)ac1.getBean("nalbean1");
b1.nalja();
NalssiOndo b2 = (NalssiOndo)ac1.getBean("nalbean2");
b2.nalssiondo();
}
}
■ 기본실습 4 (annotation-config, @Component)
□ appcont.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:p="http://www.springframework.org/schema/p"
xmlns:c="http://www.springframework.org/schema/c"
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-3.1.xsd">
<!--
지금 나는 applicationContext.xml
-->
<context:annotation-config /> <!-- bean annotation을 활성화시키는 역할 -->
<context:component-scan base-package="nalpkg1"/>
<!-- nalpkg 패키지 하위 클래스를 scan하여 bean 객체로 등록시켜준다. -->
<!--
@component를 사용하면 bean 설정 파일에 아래 같은 bean 등록 없이도 bean을 인식할 수 있다.
그리고 <context:component-scan base-package="nalpkg"/> 문장을 추가한다.
<bean id="nalbean1" class="nalpkg1.Nalja"/>
nalja
<bean id="nalbean2" class="nalpkg1.NalssiOndo"/>
nalssiondo
-->
<!--
-->
</beans>
□ nalpkg1
* Nalja.java
package nalpkg1;
import java.util.Date;
import org.springframework.stereotype.Component;
// 만약 빨간 줄 나오면
// 액박 - 마우스 - create 나오면,
// 액박처리를 권하는 줄 중에 맨 마지막에
// project fix ~~~ .jar 파일 권함
@Component
public class Nalja {
public void nalja() { // 메소드
Date d1 = new Date();
System.out.println(d1);
}
}
* NalssiOndo.java
package nalpkg1;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
@Component("ondoya") // 이름을 줌
public class NalssiOndo {
// setter x, or constructor x, xml 초기치 (c: p: x) 없어짐
// 대신 xml 파일에 <context: annotation-config/>
@Value("23") // 초기치
private int ondo;
// 처음에는 만들고 실행, 두 번째는 setter 주석달고 실행
// public void setOndo(int ondo) {
// this.ondo = ondo;
// }
public void nalssiondo() { // 메소드
System.out.println("sunny and " + ondo + "도 온도");
}
}
ㅁ hellopkg1
* Hello.java
package hellopkg1;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import nalpkg1.Nalja;
import nalpkg1.NalssiOndo;
public class Hello {
public static void main(String[] args) {
ApplicationContext ac1 = new ClassPathXmlApplicationContext("appcont.xml");
Nalja b1 = ac1.getBean("nalja", Nalja.class);
b1.nalja();
//=============================================================
// @Component에서 bena 객체 이름은 Nalja 클래스를 소문자 nalja로 해서 만든다
//=============================================================
NalssiOndo b2 = ac1.getBean("ondoya", NalssiOndo.class);
b2.nalssiondo();
}
}
■ ADI & Autowired
### Automatic Dependency Injection (DI ==> ADI)
ADI : 환경설정파일 등에서 <property>나 <construct-arg> 등을 일일이 정해주지 않더라도 자동으로 DI되는 것
ㄴ 자동 의존성 주입
### @Autowired, @Resource, @Inject ###
### @Autowired (주로 멤버변수, 생성자, 메소드 등) by 스프링
#. @Autowired는 <property>나 <construct-arg> 역할로 자동으로 같은 이름의 bean을 찾아 injection
(즉, bean 객체가 참조변수와 mapping)
예)
class Insa{
@Autowired @Value("홍길동")
private String name; // 멤버변수, 필드
.
.
.
<context:annotation-config/>
<bean id="insaBean" class="insa.Insa"></bean>
==> @Conponent에서는 bean 객체를 안 만든다 (자동으로 생성)
여기서는 bean 객체를 만든다. 물론 초기치 작업은 X
}
<@Autowired annotation / @Resource annotation / @Qualifier>
- @autowired : type 기반으로
- @Resource : 이름기반
<@Autowird 사용법>
- 자동 injection 대상에 @Autowired 사용
- xml설정에 <context:annotation-config/>설정추가
예) @Autowired
String irum;
=================================WEB에서 무조건나옴
@Contoller, @Service, @Repository, @Component(앞의 3개의 parent)의 공통점
==>bean에 자동 등록을 위해 사용
예) @Contoller
class AA{}
■ 싱글톤
□ applicationContext.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">
<!-- ==================== 나는 xml ==================== -->
<bean id="bangkaBean1" class="bangka.aa.bb.Bangka1"/>
<!--
<bean id="bangkaBean1" class="bangka.aa.bb.Bangka1" scope="singleton"/>
디폴트가 싱글톤이므로 scope 생략가능
-->
<!--
<bean id="bangkaBean2" class="bangka.aa.bb.Bangka2"/>
-->
<bean id="bangkaBean2" class="bangka.aa.bb.Bangka2" scope="prototype"/>
</beans>
□ bangka.aa.bb
* Bangka1.java
package bangka.aa.bb;
public class Bangka1 {
public void bangkabangka1(String name1) {
System.out.println("방가방가" + name1);
}
}
* Bangka2.java
package bangka.aa.bb;
public class Bangka2 {
public void bangkabangka2(String name1) {
System.out.println("방가방가" + name1);
}
}
□ hello
* Hello.java
package hello;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import bangka.aa.bb.Bangka1;
import bangka.aa.bb.Bangka2;
public class Hello {
public static void main(String[] args) {
ApplicationContext ac1 = new ClassPathXmlApplicationContext("applicationContext.xml");
// 싱글톤
Bangka1 b1 = (Bangka1)ac1.getBean("bangkaBean1");
// new 없이 di 기법으로 객체 만들어 b1에
b1.bangkabangka1("홍길동"); // 객체.메소드
System.out.println(b1); // toString()을 사용하면 확실해짐
// 방가방가홍길동
// bangka.aa.bb.Bangka1@65f095f8
Bangka1 b3 = (Bangka1)ac1.getBean("bangkaBean1");
// new 없이 di 기법으로 객체 만들어 b3에
b3.bangkabangka1("성춘향"); // 객체.메소드
System.out.println(b3);
if(b1 == b3)
System.out.println("b1, b3은 같은 인스턴스");
// 싱글톤의 문제점은
// aa에 홍길동 ==> 출력
// bb에 이도령 ==> 출력
// 동시에 출력할 때 이도령만 2번 출력하는 경우 발생
System.out.println(b1 + ", " + b3);
// 방가방가홍길동
// bangka.aa.bb.Bangka1@65f095f8
// 프로토타입
Bangka2 b2 = (Bangka2)ac1.getBean("bangkaBean2");
b2.bangkabangka2("이도령");
System.out.println(b2);
Bangka2 b4 = (Bangka2)ac1.getBean("bangkaBean2");
b2.bangkabangka2("변사또");
System.out.println(b4);
System.out.println(b2 + ", " + b4);
}
}
■ 싱글톤 2
□ applicationcontext.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">
<bean id="sawonBean1" class="sawonpkg.Sawon"/>
<!--
<bean id="sawonBean2" class="sawonpkg.Sawon"/>
-->
<bean id="sawonBean2" class="sawonpkg.Sawon" scope="prototype"/>
</beans>
□ sawonpkg
* Sawon.java
package sawonpkg;
public class Sawon {
private int id;
private String irum;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getIrum() {
return irum;
}
public void setIrum(String irum) {
this.irum = irum;
}
@Override
public String toString() {
return "Sawon [id=" + id + ", irum=" + irum + "]";
}
}
□ mainpkg
* Sawonmain.java
package mainpkg;
import org.springframework.context.support.GenericXmlApplicationContext;
import sawonpkg.Sawon;
public class Sawonmain {
public static void main(String[] args) {
GenericXmlApplicationContext ac1 = new GenericXmlApplicationContext("applicationcontext.xml");
System.out.println("Sawon 클래스, getter, setter, toString() 사용하여 출력");
// 1st 예제
Sawon b1 = (Sawon)ac1.getBean("sawonBean1"); // No new
b1.setId(3);
b1.setIrum("연수");
System.out.println(b1.toString());
Sawon b2 = (Sawon)ac1.getBean("sawonBean1");
b1.setId(5);
b1.setIrum("태식");
if(b1 == b2)
System.out.println("같은 인스턴스");
System.out.println(b1 + " " + b2); // 동시에 출력해보면 singleton 문제점 이해
// b1, b2가 같은 객체이므로 둘다 "태식"이의 객체이다.
// 2nd 예제
Sawon b11 = (Sawon)ac1.getBean("sawonBean2");
b11.setId(100);
b11.setIrum("제훈");
System.out.println(b11.toString());
Sawon b12 = (Sawon)ac1.getBean("sawonBean2");
b12.setId(110);
b12.setIrum("서준");
if(b11 == b12)
System.out.println("같은 인스턴스네");
System.out.println(b11 + " " + b12); // prototype
// b11, b12가 다른 객체이므로 동시에 출력 굿드
}
}
동시에 출력할 때 싱글톤의 문제점을 확인할 수 있다.
■ Autowired
□ appcon.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:c="http://www.springframework.org/schema/c"
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-3.1.xsd">
<!--
저쪽에서 @Autowired도 추가한다.
그러니까 참조변수와 mapping 및 bean 객체가 명시적으로 필요할 때는
<context:annotation-config/>와 @Autowired 등을 연동하여 사용한다는 것
(단, @Autowired는 해당 type bean 객체가 없거나 여러개 있으면 에러)
namespaces에서 context에 체크해야
<context:annotation-config/>를 보면 .java에서 @Autowired 등이 사용됨을 짐작함
나는 appcon.xml
-->
<context:annotation-config/>
<!--
이것 없으면 Exception in thread "main" java.lang.NullPointerException
-->
<bean id="insaBean" class="insa.Insa"></bean>
<!--
이것은 홍길동을 초기치로 전달하는 것과 연관
즉, p: x / c : x 없이 @Autowired를 통해 초기치 전달 가능
-->
<!-- <bean id="insaBean2" class="insa.Insa"></bean> -->
<!--
<bean id="insaBean2" class="insa.Insa" >
<qualifier value="insainsa"/>
</bean>
-->
<bean id="insaBean2" class="insa.Insa"/>
<!--
만일 @Autowired를 쓰면 에러
@Resource 처리시 일부러 insaBean2를 만들어본다.
-->
<!-- 아래는 그냥 객체생성을 한 것 뿐 -->
<!-- <bean id="constrargBean" class="constarg.Constarg"></bean> -->
<!--
p:insa-ref="insaBean" 없이 전달 즉 ADI에 의해 Insa클래스 객체를 초기치로 넘겨야 되는구만
-->
<bean id="constargBean" class="constarg.Constarg"/>
</beans>
□ insa
* Insa.java
package insa;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
/*
* @Autowired는 <property>나 <constructor-arg> 역할로
* 자동으로 같은 이름의 bean을 찾아 injection
* 그러므로 setter, 생성자 선언 필요 x
*
*/
public class Insa {
// private String name;
// 홍길동을 인자로 전달받고 싶다면 ?
// 위에다가 @Autowired를 사용하면 됨, 초기치는 @Value 사용
// 따라서
@Autowired
// @Qualifier("insainsa")
@Value("hong")
private String name; // setName("홍길동") // p:name = x
// ==> 나는 name에다가 mapping 할 건데 초기치는 "홍길동"이다.
// setter 안 써도됨
public String helloName(String str1) {
return this.name + "님\n" + str1;
}
}
□ constarg
* Constarg.java
package constarg;
import javax.annotation.Resource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import insa.Insa;
public class Constarg {
//############ 객체 전달 받기(초기치로) ###################
// @Autowired
// @Qualifier("moya")
@Resource(name="insaBean2") // 이름으로 // insaBean2 o, insaBean x
private Insa insa; //insa 관련 객체(기억창고)가 필드명
//여기에는 insaBean같은 insa관련 객체가 mapping
//현재 Insa클래스 관련 객체는 insaBean하나만 존재하므로
//@Autowired는 당연히 type으로 처리하면서 insaBean을 받는다
//==============================================
//요자리에 원래는 생성자 또는 setter가 있던 자리임, 당연히 생략해야
//==============================================
public String kajaHello(String str1) {
return insa.helloName(str1);
//insa객체 mapping 때문에 위처럼 insaBean객체.메소드()사용가능
}
}
// 지난번에 객체를 setter, constructor등을 통해 전달시
// xml에 p:insa-ref.......등이 필요하다
// @Autowired 에서 xml에 필요한 것은????????????
□ hello
* Hello.java
package hello;
import org.springframework.context.support.GenericXmlApplicationContext;
import constarg.Constarg;
import insa.Insa;
public class Hello {
public static void main(String[] args) {
System.out.println("<<<<<<< Hello >>>>>>>");
String str1 = "Hello, Spring";
GenericXmlApplicationContext gxac1
= new GenericXmlApplicationContext("appcon.xml");
Insa insa1 = gxac1.getBean("insaBean", Insa.class); // type을 택하므로 insaBean 이름을 명확하게 줌
// 이렇게 insaBean 이름이 필요할 경우 <bean..을 작성하는 @Autowired로 처리
// 생성자, setter 생략은 당연하다
System.out.println(insa1.helloName(str1)); // @Value...처리 setName()
Constarg con1 = gxac1.getBean("constargBean", Constarg.class); // Resource()에서 준 이름으로 처리
System.out.println(con1.kajaHello(str1));
// 결국 insaBean객체가 insa객체 기억창고 ADI로 전달되어
// insa.helloName(str1);은 insaBean.helloName(str1);으로 처리되면서
// 결과는 앞에것과 동일한 결과 출력
gxac1.close();
}
}
'IT&코딩 > 국비지원' 카테고리의 다른 글
스프링 - 2 (1) | 2023.07.12 |
---|---|
형상관리 (0) | 2023.07.10 |
Servlet - 5 (파일업로드) (0) | 2023.06.13 |
Servlet - 4 (HttpSession) (0) | 2023.06.02 |
Servlet - 3 (MVC_board) (0) | 2023.06.02 |