02월 21일(화) Spring

하이·2023년 2월 21일
0

수업

목록 보기
27/41
post-custom-banner

Spring Container

객체를 생성 : Application Context : Spring Container : Spring IoC Container : (Spring) DI Container
: 가장 주요한 작업 "bean"을 생성하고 Bean 간의 관계 설정 : Bean Factory
: Application Context가 제어권을 가지고(IoC) 직접 만들고 관계를 부여하는(Dependency) 객체 => Bean

Bean

: POJO(Plan Old Java Object)
: Spring IOC/DI Container에 의해서 관리

Bean의 주요 속성

① class
: Bean으로 등록할 Java class
② id
: Bean의 고유 식별자
: 각각의 bean을 구별하는 식별자이자 내가 일반 코드프로그램 로직, 개발자가 Bean을 요청할 때 사용 !
③ scope
: singleton, prototype
④ constructor -arg
: Bean객체 생성시 생성자에 전달할 인자
⑤ property
: Bean객체 생성시 setter에 전달할 인자

Application Context를 Bean을 사용하기 위한 설정정보가 있어야함=> Configuration MetaData => XML/Annotation

Bean 등록방법

  1. 수동방법
    : 외부 libarary를 Bean으로 등록해야하는 경우

  2. 자동방법
    : 이 방식을 이용(편하고 좋음)

수동방법

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 로 변경

  • connector-j 제거

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>

Step8

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는 일반적인 자바 클래스를 싱글톤으로

Singleton Registry

Application Context의 기능 중 하나는 Singleton Registry

왜 Singleton으로 Bean을 관리하나요?
Spring은 Server쪽 Application을 구현하기 위해서 사용함
: 여러 Client에 의해서 공유되는 객체가 필요
-> singleton으로 처리해야 효율이 좋음


의존관계(dependency)

: 두개의 class를 대상으로 함. 방향성을 명시해야 함

여기까지 배운 것
Application Context, Bean, Configuration MetaData(annotation)


Step9

XML을 이용한 설정

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



springioc 프로젝트 생성

sample1

<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);
		
	}
	
	
}

오류


sample2

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);
	}
}


sample3

VO - User.java
Sevice - interface로 생성 - UserService
UserServiceImpl

sample4

sample5

profile
기록의 즐거움 😆💻
post-custom-banner

0개의 댓글