설치(는 적는 거 생략)
pom.xml이라는 파일을 준비하면 된다. pom은 태그들로 구성되는데 우리가 직접 쓰는거 아니고 찾아서 복붙하는 방식C:\Users\사용자명\.m2\repository에서 확인 가능 <!-- top level package, artifactId는 contextPath가 된다. -->
<groupId>com.gdu</groupId>
<artifactId>app01</artifactId>
<!-- 프로젝트 이름 -->
<name>01_IoC</name>
<!-- deploy(배포) file -->
<packaging>war</packaging>
<!-- 프로젝트 버전 -->
<version>1.0.0-BUILD-SNAPSHOT</version>
<properties>이 아래에 속성 태그를 적으면 속성의 버전에 따른 디펜던시(jar)를 다운로드 받음.
기존에 적혀있는 것 하고는 버전이 달라서 우리가 수정해야할 부분들이 있음. 다음과 같이 우리가 쓰는 버전으로 수정
1. <java-version> 11
2. <org.springframework-version> 5.3.3
3. <org.aspectj-version> 1.9.6
4. <org.slf4j-version>1.7.30
맞춰준 버전
springframework 버전 : 2021년 01월 버전
org.aspectj, org.slf4j 버전 : springframework 버전과 맞추거나 이전 버전을 사용
작성된 버전 사용방법 : ${}을 이용
${java-version} -> 11으로 변경된다.
${org.springframework-version} -> 5.3.3으로 변경된다.
${org.aspectj-version} -> 1.9.6으로 변경된다.
${org.slf4j-version} -> 1.7.30으로 변경된다.
(properties랑 dependency 바꾸는 건 매번 할 필요없고 이번에 한번 만들어두고 계속 복붙하면 된다. 위에 상단 태그는 프젝마다 다 다르니까 복붙하면 안되는거 주의)
<dependencies>, <dependency>servlet-api에서 javax.servlet-api로 바꾸고 버전을 4.0.1로 바꿔줌jsp-api에서 javax.servlet.jsp-api로 바꿔주고 버전을 2.3.3으로 바꿔줌<build>maven-compiler-plugin인 것을 보면 source랑 target을 1.6으로 쓰고 있음. 이건 자바 버전을 적어주는 거라서 우리 버전이랑 맞는 11을 사용하기 위해 EL로 ${java-version}을 적어줌 (자바 버전은 상단에서 미리 지정해놨고 그 걸 사용하는 방법이 ${}라고 그랬다) <source>1.6</source> 을 <source>${java-version}</source>로 수정. target도 마찬가지
추가 방법 : Maven 레파지토리에서 원하는 것 검색한 후 dependency 째로 복사해와서 dependencies 하위로 붙여넣으면 됨. 추가한 디펜던시는 dependencies 시작하고 바로 아래에 붙여넣어주는 게 쌤의 방법이다
추가할 디펜더시
<!-- https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-databind -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.15.2</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.projectlombok/lombok -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.30</version>
<scope>provided</scope>
</dependency>
<!-- https://mvnrepository.com/artifact/com.oracle.database.jdbc/ojdbc8 -->
<dependency>
<groupId>com.oracle.database.jdbc</groupId>
<artifactId>ojdbc8</artifactId>
<version>23.2.0.0</version>
</dependency>
더 추가되면 그 수업에다가 적겠음. 롬복도 2교시에 추가된거 아니고 잭슨도 나중가서야 추가된건데 걍 적어봄
<dependency> 태그에 의해서 jar 파일이 자동으로 다운로드 된다.

쌤: 오늘은 webapp 안한다. 상단쪽을 연습하겠다. test는 db가 있을때 하는거고 그거 빼고 나머지 두개한다
프로젝트를 제어하는 권리는 원래는 개발자한테 있었음. 파일, 클래스, 객체 등등 원하는거 다 사람이 만들수 있던 걸 생각하면 됨. 스프링에서는 그 제어권을 스프링 프레임워크가 가져감. 가장 대표적인 것이 객체 생성 권한(new 어쩌구)
스프링이 new 해서 객체를 만들면 우리는 그걸 가져다가 쓰면 됨. 스프링도 인공지능은 아니니까 완전 창조하는건 아니고 우리가 써둔 코드를 보고 만들어내는거
jsp 수업할 때 dao로 싱글톤 패턴 만들던 것도 스프링에서는 다른 코드를 적으면 스프링이 자동으로 싱글톤으로 만들어줌
service도 마찬가지. jsp때는 전부 다 new ~~serviceImpl 해줬는데 스프링에서는 서비스 선언만 하면 됨
그래서 우리는 스프링에서 객체 만드는 법을 배우면 된다. 즉 스프링한테 new하라고 시키는 방법.
첫번째 방법은 xml 이용하는 것, 두번째 방법은 java 이용하는 것
xml 파일에서 <bean>이라고 하는 태그로 객체를 만들 수 있다.
getBean으로 가져다 쓸수 있다.
package src/main/resources에 xml01, src/main/java에 com.gdu.app01.xml01spring Bean Configulation File src/main/resources - xml01에 (xml 파일 이름은 자유지만) app-context.xml로 설정. next 누르면 체크하는게 나오는데 여기서 어떤걸 체크하냐에 따라 사용할 기능들의 차이가 생김. 체크안하고 그냥 생성class 객체를 만들려면 클래스가 필요함. src/main/java - com.gdu.app01.xml01에 Calculatorpublic class Calculator {
//no field
//default constructor
//method
public void add(int a, int b) {
System.out.println(a+"+"+b+"="+(a+b));
}
public void sub(int a, int b) {
System.out.println(a+"-"+b+"="+(a-b));
}
public void mul(int a, int b) {
System.out.println(a+"x"+b+"="+(a*b));
}
public void div(int a, int b) {
System.out.println(a+"/"+b+"="+(a/b));
}
}
app-context.xml
<beans> 태그 안에 <bean>태그를 만든다. bean = 객체
<!-- Calculator calc = new Calculator() -->
<bean class="com.gdu.app.xml01.Calculator" id="calc" scope="singleton"/>
class에는 객체로 만들 클래스, id는 객체 이름, scope는 싱글톤 객체인 것 지정
(스코프가 싱글톤인 것은 디폴트 값이기 때문에 생략해도 된다)
MainWrapper에서 app-context.xml 파일 읽기
ex01
public static void ex01() {
//app-context.xml 파일 읽기 (여기에서 <bean> 태그로 정의해둔 객체가 생성)
AbstractApplicationContext ctx = new GenericXmlApplicationContext("/xml01/app-context01.xml");
// <bean> 태그로 정의된 객체 가져오기
Calculator calculator = (Calculator)ctx.getBean("calc");
//ctx.getBean("calc",Calculator.class)와 동일. bean을 가져와서 캐스팅
// calc라는 이름의 bean을 가져와라 이런 뜻
// 객체 사용해보기
calculator.add(1, 2);
calculator.sub(3, 4);
calculator.mul(5, 6);
calculator.div(7, 8);
// app-context.xml 파일 닫기
ctx.close();
}
AbstractApplicationContext와 GenericXmlApplicationContext는 springframework 내장 객체다. AbstractApplicationContext가 GenericXmlApplicationContext의 부모라서 같이 쓸 수 있다. (부모, 자식, 클래스 이름 다 하나도 안중요해서 정리 안 한다함. 너무 길어서 안 쓸건데 가져다 쓰는 코드는 달라질 수 있어서 이건 오늘만 연습하면된다고 함)
GenericXmlApplicationContext가 xml을 읽고 (여기까진 확실) bean을 만들어놨다?라고 하신듯
이렇게 써주고 실행할 때는 톰캣 서버로 여는 것이 아니라 java Aplication으로 연다. 자바 main이기 때문에 자바 파일 실행하듯이 컨트롤 f11
출력결과

STS에 롬복 설치하는 거랑 롬복 jar 디펜던시 등록해주는 건 생략
생성
class com.gdu.app01.xml01에 Person (계산기를 들고 다닐 사람 만들거라 함)
사용
src/main/java
com.gdu.app01.xml01 - Person, MainWrapper
src/main/resources
xml01 - app-context.xml
Person
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@NoArgsConstructor
@AllArgsConstructor
@Data
public class Person {
private String name;
private int age;
private Calculator calculator;
}
데이터를 저장하는 객체 bean (=dto)
네트워크에서 돌아다닐 땐
관용적으로 쓰이는 말 vo
여기 머라는지 안들린다 다시
다 같은 말. 얘도 어노테이션으로 dto에 했듯이 다 달아줌
app-context.xml
<!--
1. 디폴트 생성자 + setter
Person man = new Person();
man.setName("뽀로로");
man.setAge(20);
man.setCalculator(calc);
-->
<bean class="com.gdu.app.xml01.Person" id="man">
<property name="name" value="뽀로로"/>
<property name="age" value="20"/>
<property name="calculator" ref="calc"/>
</bean>
<!--
2. 필드를 이용한 생성자
Person woman = new Person("루피", 20, calc);
-->
<bean class="com.gdu.app.xml01.Person" id="woman">
<constructor-arg value="루피"/>
<constructor-arg value="20"/>
<constructor-arg ref="calc"/>
</bean>
주석)
1번)
2번)
MainWrapper ex02
// app-context.xml 파일 읽어서 <bean> 태그로 정의된 객체 만들기
AbstractXmlApplicationContext ctx = new ClassPathXmlApplicationContext("/xml01/app-context01.xml");
// 객체 가져오기(man, woman) 두가지 방법
Person man = (Person)ctx.getBean("man");
Person woman = ctx.getBean("woman",Person.class);
// 객체 확인
System.out.println(man.getName()+", "+man.getAge());
man.getCalculator().add(1,2);
System.out.println(woman.getName()+", "+woman.getAge());
woman.getCalculator().add(3,4);
// app-context.xml 파일 닫기
ctx.close();

이제 첫번째 xml01 패키지 마무리
앞에 리눅스 보충 대해서 설명하는 건 생략.
3,4 교시랑 비슷한 수준인데 xml에 약간 새로운 내용 (이제 인용으로 하는건 다 쌤이 말한거 인용하는거다)
생성
package src/main/resources에 xml02, src/main/java에 com.gdu.app01.xml02
class com.gdu.app01.xml02에 User, Board, MainWrapper
Spring Bean Configuration File xml02에 app-context.xml > p 체크
("p" 옵션 체크로 <property> 태그를 <bean> 태그의 속성으로 넣을 수 있음. 한마디로 약식화)
/
package src/main/resources에 xml03, src/main/java에 com.gdu.app01.xml03
class com.gdu.app01.xml03에 Student, MainWrapper
Spring Bean Configuration File xml03에 app-context.xml
사용
src/main/java
com.gdu.app01.xml02 - User, Board, MainWrapper
com.gdu.app01.xml03 - Student, MainWrapper
src/main/resources
xml02 - app-context.xml
xml03 - app-context.xml
User
@NoArgsConstructor
@AllArgsConstructor
@Data
public class User {
private int userNo;
private String userId;
}
Board
@NoArgsConstructor
@AllArgsConstructor
@Data
public class Board {
private String title;
private User editor;
}
app-context.xml

생성 시 p에 체크해줘서 상단에 p 관련 한 줄 추가됨
참고) 생성 시 체크한 것들 확인 및 수정

하단에 namespace 누르면

처음 생성할 때 체크창 뜸. 여기서 확인하거나 수정할 수 잇음
namespace 없을 때는 context 파일 우클릭 > open with > spring 검색 > spring config editor 클릭 > ok
1.
<bean class="com.gdu.app.xml02.User" id="user">
<property name="userNo" value="1" />
<property name="userId" value="admin" />
</bean>
2.
<bean class="com.gdu.app.xml02.User" id="user" p:userNo="1" p:userId="admin" />
3.
<bean class="com.gdu.app.xml02.Board" id="board" p:title="공지사항" p:editor-ref="user" />
1번과 2번은 같은 코드임. 1번의 property를 p를 사용해서 속성화시킨게 2번.
3번에서는 value 대신 ref가 값으로 사용됐을 때의 코드를 확인할 수 있음. 뒤에 -ref를 붙여주면 됨
MainWrapper
이제 확인해보자
public static void main(String[] args) {
// app-context.xml 파일 읽고 <bean> 태그에 정의된 객체 생성
AbstractApplicationContext ctx = new GenericXmlApplicationContext("xml02/app-context.xml");
// 객체 가져오기
User user = ctx.getBean("user", User.class);
Board board = ctx.getBean("board",Board.class);
// 확인
System.out.println(user.getUserNo()+", "+user.getUserId());
System.out.println(board.getTitle()+", "+board.getEditor());
// app-context.xml 닫기
ctx.close();
}
확인 부분 보자. editor는 user 타입이라 userNo랑 userId도 포함하고 있어서 체이닝해서 더 들어갈 수도 있음. 예) board.getEditor().getUserNo() (그냥 이렇게 들어갈 수도 잇어서 말하신거)
출력결과

잘됐음
이제 xml02는 끝
xml03 코드
Student
@NoArgsConstructor
@AllArgsConstructor
@Data
public class Student {
private List<String> subjects;
private Set<String> contacts;
private Map<String, String> friends;
}
app-context
<bean class="com.gdu.app.xml03.Student" id="student">
<!-- List -->
<property name="subjects">
<list>
<value>국어</value>
<value>영어</value>
<value>수학</value>
</list>
</property>
<!-- Set -->
<property name="contacts">
<set>
<value>010-0000-0000</value>
<value>010-0000-0000</value>
<value>031-9999-9999</value>
</set>
</property>
<!-- Map -->
<property name="friends">
<map>
<entry key="동네친구" value="루피"></entry>
<entry key="학교친구" value="뚜비"></entry>
<entry key="사회친구" value="포비"></entry>
</map>
</property>
</bean>
MainWrapepr
실행해보기
public static void main(String[] args) {
//app-context.xml에 정의된 <bean> 태그를 객체로 생성
AbstractApplicationContext ctx = new GenericXmlApplicationContext("xml03/app-context.xml");
//객체 가져오기
Student s = ctx.getBean("student", Student.class);
// 확인
for(String subject : s.getSubjects()) {
System.out.println(subject);
}
for(String contact: s.getContacts()) {
System.out.println(contact);
}
for(Entry<String, String> entry : s.getFriends().entrySet()) {
System.out.println(entry.getKey()+","+entry.getValue());
}
}
for문 돌릴때 map은 entrySet이 포함되어야 해서 getFriends()뒤에 entrySet() 체이닝해준 것 주의하기
(반환타입이 Entry라서 그런가. 다른 애들은 단순 String이고)
출력결과

list = 국어 영어 수학
set = 010-0000-0000 031-9999-9999 (중복은 제거된 것)
나머지는 map
전부 다 제대로 출력됐음
문제 내줬는데 이전 교시에 배운 내용들로 property 태그나 constructor-arg 태그 이용해서 데이터 넣기 그런거다. 블로그에 적는거 생략
갑자기 피피티로 넘어감

중요한건 객체들을 만드는 방법이다.
<bean>태그를 이용하는 방법 (오늘 한 거)
@Configuration과 @Bean 어노테이션을 이용하는 방법 (나중에 배울거임)
객체를 가져다 쓰는 방법은
getBean() (하고 있는것. 나머지는 mvc할 때 수업)
@Inject
@Autowired
getBean은 별로 중요하지 않다. 가져다 쓰는 건 나중에 어노테이션을 직접 쓸 때 중요한 것 (겟빈 밑에 두개가 중요하다는건가)

지금은 mvc까지 가져가지 않아서 일일이 Spring Bean Configuration File을 작성하고 있지만 mvc까지 가져가면 Spring Bean Configuration File 우리가 안 만든다.
Spring Bean Configuration File이 root-context와 servlet-context라는 두 개의 파일 형태로 만들어져 있을 것이다.
두번째 문제 설명
데이터베이스 작업
모든 db 선행작업은 connection (Connection con 만들어서 사용하는 방식)
이 때 커넥션 만들어서 쓰는 방법: 1. jdbc, 2. DataSource (DBCP(데이터베이스 커넥션 풀))로 나눌 수 있음
어쨋든 DriveManager로부터 getConnection을 얻어오는 이 과정을 스프링의 도움을 받아 진행해보자
MyJdbcConnection
@NoArgsConstructor
@AllArgsConstructor
@Data
public class MyJdbcConnection {
private String driver; // oracle.jdbc.OracleDriver
private String url; // jdbc:oracle:thin:@127.0.0.1:1521:xe
private String user; // GD
private String password; // 1111
public Connection getConnection() {
Connection con = null;
try {
Class.forName(driver); //driver 읽어들임
con = DriverManager.getConnection(url, user, password); //커넥션 얻어오는 작업
System.out.println(user + " 접속 성공"); //커넥션 만들어졌다면 출력됨
} catch (Exception e) {
e.printStackTrace();
}
return con;
}
}
필드에 저장되어야 하는 이름은 항상 같다고 함. (근데 나 jdbc 때 수업 아파서 학원 빠져서 잘 모르는거 감안..) 무튼 옆에 적어준 주석들이 항상 각 필드의 이름으로 저장되어 있어야 한다고 함. GD랑 1111은 데베 배울때부터 쓰던거라 내 데베랑 연결하기 위해 저런 이름이 나온것 같네 아무튼 ㅇㅋ
저 주석으로 적어준 값들을 지금까지 배운 두가지 방법으로 넣어주면 되는 것 같다.
답
<!-- MyJdbcConnection 객체 만들기 -->
<bean class="com.gdu.app02.xml02.MyJdbcConnection" id="myJdbcConnection">
<property name="driver" value="oracle.jdbc.OracleDriver" />
<property name="url" value="jdbc:oracle:thin:@127.0.0.1:1521:xe" />
<property name="user" value="GD" />
<property name="password" value="1111" />
</bean>
MyJdbcDao
public class MyJdbcDao {
private Connection con; //MyjdbcConnection의 getConnection()클래스로부터 얻어진다(con이 return되고 있음)
private AbstractApplicationContext ctx;
private MyJdbcConnection myJdbcConnection;
private Connection getConnection() {
ctx = new GenericXmlApplicationContext("xml02/appCtx.xml"); // 1
myJdbcConnection = ctx.getBean("myJdbcConnection", MyJdbcConnection.class); //2
ctx.close(); // 3
return myJdbcConnection.getConnection(); //4
}
private void close() {
try {
if(con != null) {
con.close();
System.out.println(myJdbcConnection.getUser() + " 접속 해제");
}
} catch (Exception e) {
e.printStackTrace();
}
}
public void add() {
con = getConnection();
System.out.println("add() 호출");
close();
}
public void remove() {
con = getConnection();
System.out.println("remove() 호출");
close();
}
public void modify() {
con = getConnection();
System.out.println("modify() 호출");
close();
}
public void select() {
con = getConnection();
System.out.println("select() 호출");
close();
}
}
dao = 하고 싶은 작업을 메소드로 만들어주는 것
1. appCtx에 정의해준 bean 태그를 객체로 생성 (appCtx.xml 작업보다 이거 먼저한듯)
2. myJdbcConnection 가져오기
3. 1번과 2번하면 myJdbcConnection 객체 나온거니까 닫아줌
4. 호출 결과 반환. 즉 connection을 반환하는 getConnection()이었음
getConnection()을 private로 만들어줬으니 이 클래스 내부에서 사용한다는 의미. 모든 메소드들에 커넥션 호출한다는 뜻인 con = getConnection()을 달아준다. 그러면 myJdbcConnection의 getConnection()도 사용할 수 있음 => (이렇게 db 사용가능해질듯)
원리만 보려고 한거라서 각 메소드 본문 채우지 않고 메소드마다 호출됐다는 것만 출력시켜줌. 메시지 출력되면 커넥션도 제대로 가져와진 것
그러면 문제. myJdbcDao를 싱글톤으로 제작해보라.
힌트. 객체 만들려면 xml 열어서 써야함.
정답
appCtx
<!-- MyJdbcDao 객체 만들기 -->
<bean class="com.gdu.app02.xml02.MyJdbcDao" id="dao"/>
끝.
property같은 걸로 필드 커넥션 채우면 안되는 것 주의.
dao는 커넥션 미리 채우는 거 아니다. 메시지 호출할 때만 생겼다 없어졌다 하는거임.
해결
다른 질문. 그러면 mvc패턴에서 dao를 부르는건 무엇인가.
힌트: db를 부르는 계층의 이름
-> Service 계층
(컨트롤러가 서비스 부르고 서비스가 dao 부름)
원래는 인터페이스로 만드는데 지금은 구현체 형태만 보는거니까 그냥 클래스로 만들음
MyJdbcService
public class MyJdbcService {
private MyJdbcDao myJdbcDao;
public void add() {
myJdbcDao.add();
}
public void remove() {
myJdbcDao.remove();
}
public void modify() {
myJdbcDao.modify();
}
public void select() {
myJdbcDao.select();
}
}
마지막 미션. MyJdbcService을 객체로 만들기
힌트. myJdbcDao의 값을 채워야 함
정답
우선 setter를 이용해서 값을 저장할 수 있도록 MyJdbcService에
@NoArgsConstructor
@AllArgsConstructor
@Data
어노테이션 달아주기
본격적으로 객체를 만드는 작업은 appCtx.xml에서 service가 가지고 있는 단 하나의 필드인 MyJdbcDao myjdbcDao;를 채워주면 됨
<!-- MyJdbcService 객체 만들기 -->
<bean class="com.gdu.app02.xml02.MyJdbcService" id="service">
<property name="myJdbcDao" ref="dao"/>
</bean>
채워주기 위해서는 property 태그가 필요. 값으로 바로 위에서 만든 dao(MyJdbcDao 객체)를 넣어줌. bean 태그로 만들어져있는 객체이므로 value가 아닌 ref으로 값을 준다.
이건 실전으로 써도 되는 구조다.
MainWrapper
실행해보기(원래는 컨트롤러로 해야하는데 그냥 대충 해본 거니까)
public static void main(String[] args) {
AbstractApplicationContext ctx = new GenericXmlApplicationContext("xml02/appCtx.xml");
MyJdbcService myJdbcService = ctx.getBean("service", MyJdbcService.class);
myJdbcService.add();
myJdbcService.remove();
myJdbcService.modify();
myJdbcService.select();
ctx.close();
}
service가 dao를 물고 dao가 connection을 물은 전부 연결된 구조라서 service가 잘 돌면 dao도 잘 돌고 connection도 잘 돌음
출력결과
호출 메시지 다 뜬다. 다만 db랑 실제로 연결된 건 아니라서
코드 개선만 하고 넘어감. 난 개선된 코드로 설명햇음
getConnection() 새로 파준거