객체를 생성 : Application Context : Spring Container : Spring IoC Container : (Spring) DI Container
: 가장 주요한 작업 "bean"을 생성하고 Bean 간의 관계 설정 : Bean Factory
: Application Context가 제어권을 가지고(IoC) 직접 만들고 관계를 부여하는(Dependency) 객체 => Bean
: POJO(Plan Old Java Object)
: Spring IOC/DI Container에 의해서 관리
① class
: Bean으로 등록할 Java class
② id
: Bean의 고유 식별자
: 각각의 bean을 구별하는 식별자이자 내가 일반 코드프로그램 로직, 개발자가 Bean을 요청할 때 사용 !
③ scope
: singleton, prototype
④ constructor -arg
: Bean객체 생성시 생성자에 전달할 인자
⑤ property
: Bean객체 생성시 setter에 전달할 인자
Application Context를 Bean을 사용하기 위한 설정정보가 있어야함=> Configuration MetaData => XML
/Annotation
수동방법
: 외부 libarary를 Bean으로 등록해야하는 경우
자동방법
: 이 방식을 이용(편하고 좋음)
class MyResource {
}
: 등록하기 위한 설정정보가 있어야함(annotation
을 이용해서 처리)
=>
객체를 만드는 method를 bean으로 등록
@Configuration //자동으로 bean으로 등록
class MyResource {
//얘는 수동으로 bean 등록
@Bean //Bean ID
public MyResource getResource(){
return new MyResource
}
}
@Component
가 붙은 클래스는 자동으로 Bean으로 등록됨
- 하위 annotaion
:@Contrller
,@Service
,@Repository
,@Configuration
: 자동으로 등록하는 경우, class 이름의 앞글자를 소문자로 바꿔서 Bean의 ID로 지정됨
Maven Project 로 변경
pom.xml에 추가
<dependencies>
<!-- https://mvnrepository.com/artifact/org.springframework/spring-context -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.3.20</version>
</dependency>
<!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.28</version>
</dependency>
</dependencies>
package step8;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import step8.dao.UserDao;
import step8.vo.User;
public class UserDaoTest {
public static void main(String[] args) throws Exception {
// 1. 사용자를 입력해보자 - 사용자 VO생성
User user = new User();
user.setId("hong");
user.setPassword("1234");
user.setName("홍길동");
// UserDao dao = new DaoFactory().userDao();
// DaoFactory에 bean이 있음. 그럼 알아서 등록해줌
ApplicationContext context = new AnnotationConfigApplicationContext(DaoFactory.class);
// Bean의 고유 id, class를
UserDao dao = context.getBean("userDao", UserDao.class);
// ApplicationContext를 생성한 후 이 ApplicatioContext에게
// UserDao객체를 요청해서 받아와서 사용할거에요
// 3. 사용자 입력
dao.insert(user);
System.out.println("사용자 등록성공");
// 4. 사용자 조회
User result = dao.select("hong");
System.out.println(result.getName()); // 홍길동
}
}
package step8;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import step8.dao.ConnectionMaker;
import step8.dao.SimpleMakeConnection;
import step8.dao.UserDao;
@Configuration
public class DaoFactory {
@Bean // Bean id
public UserDao userDao() {
UserDao dao = new UserDao(connectionMaker());
return dao;
}
@Bean
public ConnectionMaker connectionMaker() {
return new SimpleMakeConnection();
}
}
package step8.dao;
import java.sql.Connection;
import java.sql.DriverManager;
public class SimpleMakeConnection implements ConnectionMaker {
public SimpleMakeConnection() {
System.out.println("SimpleMakeConnection 생성자 호출");
}
@Override
// 별도의 class로 분리시킴
public Connection getConnection() throws Exception {
// 1. Driver Loading
Class.forName("com.mysql.cj.jdbc.Driver");
// 2. 연결
String jdbcUrl = "jdbc:mysql://127.0.0.1:3306/spring?characterEncoding=UTF-8&serverTimezone=UTC&useSSL=false&allowPublicKeyRetrieval=true";
String id = "root";
String pw = "test1234";
Connection con = DriverManager.getConnection(jdbcUrl, id, pw);
return con;
}
}
package step8.dao;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import step8.vo.User;
// Database 처리하는 코드
// 2개의 method를 작성할 거에요
// 사용자 입력, 조회
public class UserDao {
// 클래스이름, 필드명
ConnectionMaker connectionMaker;
// Injection이 발생 !!
// Injection은 1.생성자를 통한 주입이 있고, 2.setter를 통한 주입이 있음(step9)
// 1. 생성자를 통한 주입
public UserDao(ConnectionMaker connectionMaker) {
this.connectionMaker = connectionMaker;
System.out.println("UserDao 생성자 호출");
}
public void insert(User user) throws Exception {
// pure JDBC를 이용해서 DB처리를 해보자
// 6단계 !!
// 1,2단계를 위로 빼주고
// connection 연결
Connection con = connectionMaker.getConnection();
// 3. PreparedStatement를 만들자
String sql = "INSERT INTO users VALUES (?, ?, ?)";
PreparedStatement pstmt = con.prepareStatement(sql);
pstmt.setString(1, user.getId());
pstmt.setString(2, user.getPassword());
pstmt.setString(3, user.getName());
// 4. SQL구문 실행
int result = pstmt.executeUpdate();
// 5. 결과처리
if (result == 1) {
System.out.println("정상적으로 입력되었어요");
}
// 6. resource 해제
pstmt.close();
con.close();
}// insert
public User select(String userId) throws Exception {
// 1,2단계를 위로 빼주고
// connection 연결
Connection con = connectionMaker.getConnection();
// 3. PreparedStatement를 만들자
String sql = "SELECT * FROM users WHERE id = ?";
PreparedStatement pstmt = con.prepareStatement(sql);
pstmt.setString(1, userId);
// 4. SQL구문 실행
ResultSet result = pstmt.executeQuery();
// 5. 결과처리
result.next();
User user = new User();
user.setId(result.getString("id"));
user.setPassword(result.getString("password"));
user.setName(result.getString("name"));
// 6. resource 해제
pstmt.close();
con.close();
return user;
} // select
}
step7
step8
: application Context는 일반적인 자바 클래스를 싱글톤으로
Application Context의 기능 중 하나는 Singleton Registry
왜 Singleton으로 Bean을 관리하나요?
Spring은 Server쪽 Application을 구현하기 위해서 사용함
: 여러 Client에 의해서 공유되는 객체가 필요
-> singleton으로 처리해야 효율이 좋음
: 두개의 class를 대상으로 함. 방향성을 명시해야 함
여기까지 배운 것
Application Context, Bean, Configuration MetaData(annotation)
: xml file이 있어야 함
: xml은 문서의 구조가 미리 정해진 형태로 만들어졌는지 검증하는 기능이 있음(즉, 어떤 XML이냐에 따라 사용 가능한 Tag와 Tag의 구조가 이미 결정되어있음) => 2로 검증을 수행
① DTD
② Schema -> namespace를 이용해서 추가적인 기능을 포함 가능
스키마를 이용한 ! applicationContext.xml
package step9;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import step9.dao.ConnectionMaker;
import step9.dao.SimpleMakeConnection;
import step9.dao.UserDao;
@Configuration
public class DaoFactory {
@Bean // Bean id
public UserDao userDao() {
// UserDao dao = new UserDao(connectionMaker());
UserDao dao = new UserDao(new SimpleMakeConnection());
dao.setConnectionMaker(connectionMaker());
return dao;
}
@Bean
public ConnectionMaker connectionMaker() {
return new SimpleMakeConnection();
}
}
package step9.dao;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import step9.vo.User;
// Database 처리하는 코드
// 2개의 method를 작성할 거에요
// 사용자 입력, 조회
public class UserDao {
// 클래스이름, 필드명
ConnectionMaker connectionMaker;
// Injection이 발생 !!
// Injection은 1.생성자를 통한 주입이 있고, 2.setter를 통한 주입이 있음
public UserDao() {
System.out.println("UserDao 기본 생성자 호출");
}
// 1. 생성자를 통한 주입
public UserDao(ConnectionMaker connectionMaker) {
this.connectionMaker = connectionMaker;
System.out.println("UserDao 인자 있는 생성자 호출");
}
// 2. setter를 통한 주입
public void setConnectionMaker(ConnectionMaker connectionMaker) {
this.connectionMaker = connectionMaker;
System.out.println("setConnectionMaker setter 호출");
}
public void insert(User user) throws Exception {
// pure JDBC를 이용해서 DB처리를 해보자
// 6단계 !!
// 1,2단계를 위로 빼주고
// connection 연결
Connection con = connectionMaker.getConnection();
// 3. PreparedStatement를 만들자
String sql = "INSERT INTO users VALUES (?, ?, ?)";
PreparedStatement pstmt = con.prepareStatement(sql);
pstmt.setString(1, user.getId());
pstmt.setString(2, user.getPassword());
pstmt.setString(3, user.getName());
// 4. SQL구문 실행
int result = pstmt.executeUpdate();
// 5. 결과처리
if (result == 1) {
System.out.println("정상적으로 입력되었어요");
}
// 6. resource 해제
pstmt.close();
con.close();
}// insert
public User select(String userId) throws Exception {
// 1,2단계를 위로 빼주고
// connection 연결
Connection con = connectionMaker.getConnection();
// 3. PreparedStatement를 만들자
String sql = "SELECT * FROM users WHERE id = ?";
PreparedStatement pstmt = con.prepareStatement(sql);
pstmt.setString(1, userId);
// 4. SQL구문 실행
ResultSet result = pstmt.executeQuery();
// 5. 결과처리
result.next();
User user = new User();
user.setId(result.getString("id"));
user.setPassword(result.getString("password"));
user.setName(result.getString("name"));
// 6. resource 해제
pstmt.close();
con.close();
return user;
} // select
}
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="connectionMaker" class="step9.dao.SimpleMakeConnection" />
<bean id="userDao" class="step9.dao.UserDao">
<!-- name="setter" setter 호출 ref = "Bean의 id" -->
<property name="connectionMaker" ref="connectionMaker"></property>
</bean>
</beans>
<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>springioc</groupId>
<artifactId>springioc</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>5.3.23</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>
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="messagebean" class="springioc.sample1.MessageBeanImpl">
<constructor-arg>
<!-- 생성자를 만들 때 딸기라는 value를 줌 -->
<value>딸기</value>
</constructor-arg>
<property name="cost">
<value>3000</value>
</property>
</bean>
</beans>
package springioc.sample1;
public interface MessageBean {
// 인터페이스는 앞에 public abstract 생략
void sayHello();
}
package springioc.sample1;
public class MessageBeanImpl implements MessageBean {
private String fruit;
private int cost;
public MessageBeanImpl() {
System.out.println("MessageBeanImpl 기본 생성자 호출");
}
public MessageBeanImpl(String fruit) {
this.fruit = fruit;
System.out.println("MessageBeanImpl 생성자 호출 - " + fruit);
}
public void setCost(int cost) {
this.cost = cost;
}
@Override
public void sayHello() {
System.out.println(fruit + ", " + cost);
}
}
오류
Bar.java
package springioc.sample2;
public class Bar {
public Bar() {
System.out.println("Bar의 기본 생성자 호출");
}
}
Foo.java
package springioc.sample2;
public class Foo {
public Foo() {
System.out.println("Foo의 기본생성자 호출");
}
public Foo(String str) {
System.out.println("Foo의 기본생성자 호출 - " + str);
}
public Foo(String str, int num) {
System.out.println("Foo의 기본생성자 호출 - " + str + ", " + num);
}
public Foo(Bar bar) {
System.out.println("Foo의 기본생성자 호출 - " + bar);
}
}
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="foo0" class="springioc.sample2.Foo"></bean>
<bean id="foo1" class="springioc.sample2.Foo">
<constructor-arg value="abc" />
</bean>
<bean id="foo2" class="springioc.sample2.Foo">
<constructor-arg index="0" type="java.lang.String" value="abc" />
<constructor-arg index="1" type="int" value="1000" />
</bean>
<bean id="myBar" class="springioc.sample2.Bar">
</bean>
<bean id="foo3" class="springioc.sample2.Foo">
<constructor-arg ref="myBar"></constructor-arg>
</bean>
</beans>
Test.java
package springioc.sample2;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class Test {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml", Bar.class);
}
}
VO - User.java
Sevice - interface로 생성 - UserService
UserServiceImpl