Spring 기초 : 의존성 주입(DI)

부트캠프(END)/-Spring|2022. 8. 23. 12:52

DI란 Dependency Injection으로, 의존성 주입이라는 의미를 가지고 있다.

AOP와 더불어 스프링의 주된 개발 방식이다.

 

DI는 객체에 속성값을 주입하여 모듈간의 결합도를 낮추고 유연한 코딩이 가능하도록 돕는다.

즉, 유지보수가 쉽도록 세팅할 수 있다!

 

DI는 크게 3종류가 있다.

p: 속성으로 prpoerty를 세팅하고, c: 속성으로 생성자를 세팅하고,

메서드  DI → 객체 생성시/소멸시에 사용하는 init-method와 destroy-method를 등록한다.

메서드는 자동 로그인이나 쿠키, 드라이버 등록 등에 활용할 수 있다.

간단한 예시!  ↓

<?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"
  xsi:schemaLocation="http://www.springframework.org/schema/beans 
  http://www.springframework.org/schema/beans/spring-beans.xsd">
  <bean id="student1" class="doodoo.dev.spring_methodDI.Student"
    p:sno="1"
    p:name="kim"
    p:kor="98"
    p:eng="100"
    p:math="87"
    init-method="init"
    destroy-method="destroy"
  />
</beans>

 

 

스프링의 핵심은 DI와 AOP!

 

 

스프링에서는 XML파일(Spring Bean Configuration File)이나

자바로 구현한 Config클래스, 어노테이션 등을 활용해서 의존성을 관리할 수 있다.

 

 

 

우선 간단한 예제를 하나 보자.

 

XML파일로 의존성 주입하기

 

1. db라는 properties 파일에 데이터베이스 연결 정보를 저장하고, 

 

db.properties

driver=oracle.jdbc.driver.OracleDriver
url=jdbc:oracle:thin:@localhost:1521:XE
username=user
password=pwd

 

 

2. 이 파일을 app.xml(Spring Bean Configuration)에서 읽어 mybatis로 전송해서 연결하고,

그 연결정보를 DAO에까지 전송해서 원하는 데이터를 불러오자.

 

app.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:util="http://www.springframework.org/schema/util"
	xsi:schemaLocation="http://www.springframework.org/schema/beans 
		http://www.springframework.org/schema/beans/spring-beans.xsd
		http://www.springframework.org/schema/util 
		http://www.springframework.org/schema/util/spring-util-4.3.xsd">
	<!-- myBatis 연결 +보안! 연결정보를 따로 파일(db.properties)에 저장 -->
	<!-- 1.정보 읽기 (src/main/java 여기를 classpath라고 함)-->
	<util:properties id="db" location="classpath:db.properties"></util:properties>
	<!-- 2.정보를 모아서 mybatis로 전송 : BasicDataSource가 데이터베이스 연결 정보를 다 갖고있음! -->
	<bean id="ds" class="org.apache.commons.dbcp.BasicDataSource"
	 p:driverClassName="#{db['driver']}"
	 p:url="#{db['url']}"
	 p:username="#{db['username']}"
	 p:password="#{db['password']}"
	/>
	<!-- 3.myBatis = SqlSessionFactoryBean이 받아서 연결과 해제를 만든다 -->
	<bean id="ssf" class="org.mybatis.spring.SqlSessionFactoryBean"
	 p:dataSource-ref="ds"
	 p:configLocation="classpath:Config.xml"
	/>
	<!-- 4.DAO에 전송 (DAO에서 SqlSessionDaoSupport 상속받아놔야 함)-->
	<bean id="dao" class="doodoo.dev.di.MovieDAO"
	 p:sqlSessionFactory-ref="ssf"
	/>
</beans>

 

 

3. VO와 mapper파일을 등록해서 myBatis가 인식할 수 있도록 해 준다.

 

Config.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
	<typeAliases>
		<typeAlias type="doodoo.dev.di.MovieVO" alias="MovieVO"/>
	</typeAliases>
	<mappers>
		<mapper resource="doodoo/dev/di/movie-mapper.xml"/>
	</mappers>
</configuration>

 

더보기
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" 
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="movie-mapper">
 <select id="movieListData" resultType="MovieVO" parameterType="hashmap">
  SELECT mno, cno, title, director, genre, actor, num
  FROM (SELECT mno, cno, title, director, genre, actor, rownum as num
  FROM (SELECT mno, cno, title, director, genre, actor
  FROM project_movie ORDER BY mno ASC))
  WHERE num BETWEEN #{start} AND #{end}
 </select>
</mapper>

 

4. MovieDAO에서 SqlSessionDaoSupport를 상속받아 메서드를 구현한다.

 

MovieDAO.java

package doodoo.dev.di;

import org.mybatis.spring.support.SqlSessionDaoSupport;
import java.util.*;
public class MovieDAO extends SqlSessionDaoSupport {
  public List < MovieVO > movieListData(Map map) {
    //엄청 간단~~~~~ 
    return getSqlSession().selectList("movieListData", map);
  }
}

 

 

5. 그리고 MainClass에서 실행해주면 끝~~

 

MainClass.java

package doodoo.dev.di;
import java.util.*;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class MainClass {

  public static void main(String[] args) {
    ApplicationContext app = new ClassPathXmlApplicationContext("app.xml");
    //얘가 Spring세팅을 불러오는 역할, MovieDAO를 갖고 있다.
    //이제 MovieDAO dao = new MovieDAO() 이렇게 안함 -> nullPointException 발생한다.
    //스프링 안에 있는 객체만 DAO를 갖고 있기 때문에... new로는 ssf등의 정보를 받지 못한 상태이기 때문에 null임
    Scanner scan = new Scanner(System.in);
    System.out.print("페이지 입력:");
    int page = scan.nextInt();

    int rowSize = 10;
    int start = (rowSize * page) - (rowSize - 1);
    int end = rowSize * page;
    Map map = new HashMap();
    map.put("start", start);
    map.put("end", end);

    MovieDAO dao = (MovieDAO) app.getBean("dao"); //스프링이 갖고 있는 객체를 얻어 옴!
    List < MovieVO > list = dao.movieListData(map);
    for (MovieVO vo: list) {
      System.out.println(vo.getMno() + "." + vo.getTitle());
    }
  }
}

 

주의할 점

bean에 등록된 id로 생성한 객체는 싱글톤 패턴으로 구현된다.

즉, 아래와 같이 동일한 bean ID로 생성된 dao1과 dao2, dao3 객체는 모두 주소가 같다.

MovieDAO dao1 = (MovieDAO) app.getBean("dao");
MovieDAO dao2 = (MovieDAO) app.getBean("dao");
MovieDAO dao3 = (MovieDAO) app.getBean("dao");

따라서, Spring Bean Configuration에 VO(데이터형)와 MainClass(클라이언트)는 등록하지 않는다.

싱글톤 패턴을 디폴트로 구현되기 때문에... 리스트 형태로 데이터를 받아오거나 할 때 곤란하다.

DAO, Manager, Service, ... 등의 컴포넌트들은 등록해서 사용한다.

→ 이런 컴포넌트들을 모아서 관리하는 게 컨테이너 == 스프링은 일종의 컨테이너!

 

 

 

 

어노테이션으로 의존성 주입

component-scan을 이용해 패키지를 통째로 읽어오고,

어노테이션을 이용해 내가 지정한 것만 메모리를 할당하도록 세팅해 보자.

 

[Spring 어노테이션의 종류]
1. 메모리 할당
@Component : 일반 클래스(~Manager, MainClass) , 라이브러리 클래스 등
@Respository : 저장소(~DAO)
@Service : BI(통합) = DAO 여러 개를 통합할 때 사용한다
@Controller : Model(JSP)
@RestController : Model(Javascript)
@ControllerAdvice : 통합 예외 처리
@Configuration : XML 대신 자바로 환경 설정할 때 사용한다.

2. 값 주입
@Autowired : 스프링에서 자동으로 객체에 값 주입

3. 웹 관련 어노테이션..은 일단 생략~

 

 

이 예제에서 필요한 파일들

 

1. Spring Bean Configuration 파일에서 context:component-scan 태그를 이용해,

doodoo.dev.anno 패키지 안에 있는 모든 파일을 등록하도록 설정한다.

 

app.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: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-4.3.xsd">
	<context:component-scan base-package="doodoo.dev.anno"/> 
</beans>

 

2. BasicDataSource를 상속받은 클래스 MyBasicDataSource에 데이터베이스 연결 정보를 저장하고,
@Component 어노테이션으로 메모리를 할당한다. (
이 때, 해당 클래스의 아이디로 "ds"를 함께 등록한다.)

 

MyBasicDataSource.java

package doodoo.dev.anno;

import org.apache.commons.dbcp.BasicDataSource;
import org.springframework.stereotype.Component;
/*
 * <bean id="ds" class="org.apache.commons.dbcp.BasicDataSource"
	 p:driverClassName="#{db['driver']}"
	 p:url="#{db['url']}"
	 p:username="#{db['username']}"
	 p:password="#{db['password']}"
	/>
 */
@Component("ds") //메모리 할당 요청
public class MyBasicDataSource extends BasicDataSource {
  public MyBasicDataSource() {
    setDriverClassName("oracle.jdbc.driver.OracleDriver");
    setUrl("jdbc:oracle:thin:@localhost:1521:XE");
    setUsername("username");
    setPassword("password");
  }
}

 

 

3. 데이터를 받아 오는 데 사용하는 mapper 파일과 VO클래스도 Config.xml 에 등록해 준다.

 

Config.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
  <typeAliases>
    <typeAlias type="doodoo.dev.anno.MovieVO" alias="MovieVO"/>
  </typeAliases>
  <mappers>
    <mapper resource="doodoo/dev/anno/movie-mapper.xml"/>
  </mappers>
</configuration>

 

 

4. SqlSessionFactoryBean을 상속받아 SqlSession 클래스를 구현하면서,

앞서 생성한 DataSource와 Config.xml을 SQL세션에 등록해 준다.

 

@Autowired를 이용하면 메서드 setDataSource(DataSource dataSource) 의 매개변수로

아까 생성한 DataSource 객체의 주소를 자동으로 입력할 수 있다.

 

MySqlSessionFactoryBean.java

package doodoo.dev.anno;

import javax.sql.DataSource;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource;
import org.springframework.stereotype.Component;
/*
    <bean id="ssf" class="org.mybatis.spring.SqlSessionFactoryBean"
	 p:dataSource-ref="ds"
	 p:configLocation="classpath:Config.xml"
	/>
 */
@Component("ssf") //@Target(value={TYPE}) 반드시 클래스에서만 사용해야 한다. == 클래스 위에 설정해야 한다
public class MySqlSessionFactoryBean extends SqlSessionFactoryBean {
  @Autowired //자동 주입! (객체의 주소값을 주입할 때)
  /* @Target(value={ANNOTATION_TYPE, CONSTRUCTOR, FIELD, METHOD, PARAMETER})
   * ANNOTATION_TYPE : 어노테이션 위에 올라가는 어노테이션
   * CONSTRUCTOR : 생성자
   * FIELD : 멤버 변수
   * METHOD : 메서드
   * PARAMETER : 매개 변수
   * 
   * 자동 주입의 단점 : 같은 유형의 클래스를 주입하면 오류가 난다.
   * (같은 유형의 클래스일 때는 @Qualifier를 이용해서 특정 객체를 지정한다.)
   * -> @Autowired+@Qualifier = @Resource - 근데 요새는 잘 안 쓴다. JDK1.8까지만 사용이 가능하기때문에...
   */
  public void setDataSource(DataSource dataSource) { //datasource 위치에 해당 객체의 주소값을 넣어라
    //MyBasicDataSource가 여기로 들어올 것임
    super.setDataSource(dataSource);
  }
  public MySqlSessionFactoryBean() {
    try {
      Resource res = new ClassPathResource("Config.xml");
      setConfigLocation(res);
    } catch (Exception ex) {}
  }
}

 

5.  SqlSessionDaoSupport를 상속받아 DAO를 구현한다!

 

마찬가지로, @Autowired 어노테이션을 이용해서 setSqlSessionFactory() 메서드의 매개변수로 

아까 생성한 MySqlSessionFactoryBean의 객체 주소를 자동으로 입력하여 Sql세션을 등록한다.

 

MovieDAO.java (Class)

package doodoo.dev.anno;

import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.support.SqlSessionDaoSupport;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;
import java.util.*;

@Repository
public class MovieDAO extends SqlSessionDaoSupport {
  @Autowired //MySqlSessionFactoryBean에서 받아온 값을 여기에 채워넣어달라
  public void setSqlSessionFactory(SqlSessionFactory sqlSessionFactory) {
    super.setSqlSessionFactory(sqlSessionFactory);
  }

  public List < MovieVO > movieListData(Map map) {
    //엄청 간단~~~~~ 
    return getSqlSession().selectList("movieListData", map);
  }

}

 

 

5. MainClass를 @Component로 등록하면서 불러와 원하는 메서드를 실행해 준다.

 

MainClass.java

package doodoo.dev.anno;
import java.util.*;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.stereotype.Component;
@Component("mc")
public class MainClass {
  @Autowired
  private MovieDAO dao; //스프링에 생성된 dao의 주소값을 주입해 준다(스프링에서 getBean() 대신 처리함)
  public static void main(String[] args) {
    ApplicationContext app = new ClassPathXmlApplicationContext("app.xml");
    MainClass mc = (MainClass) app.getBean("mc");
    Map map = new HashMap();
    map.put("start", 1);
    map.put("end", 10);
    List < MovieVO > list = mc.dao.movieListData(map);
    for (MovieVO vo: list) {
      System.out.println(vo.getMno() + "." + vo.getTitle());
    }

  }
}

 

 

 

 

Autowired의 단점 

위 예제에서 볼 수 있었듯 @Autowired를 사용하면 상황에 따라

그에 맞는 적절한 클래스 객체의 주소를 자동으로 입력해 줄 수 있어 굉장히 편리하다.

하지만 비슷한 클래스가 여러 개가 있을 경우 @Autowired 하나만으로는 원하는 객체를 불러오지 못한다.

 

 

*Config.xml 안썼음

예를 들어, DataBase라는 인터페이스가 있고, 

이를 구현한 클래스 Oracle과 MySQL이 있다고 해 보자.

그리고 두 클래스는 각각 @Repository 어노테이션을 붙여 주면서 다른 아이디로 등록해 주었다.

 

DataBase.java (Interface)

package doodoo.dev.auto;

public interface DataBase {
  public void getConnection();
  public void disConnection();
}

Oracle.java (Class)

package doodoo.dev.auto;

import org.springframework.stereotype.Repository;

@Repository("ora")
public class Oracle implements DataBase {
  @Override
  public void getConnection() {
    System.out.println("Oracle 연결");
  }
  @Override
  public void disConnection() {
    System.out.println("Oracle 연결 해제");
  }
}

MySQL.java (Class)

package doodoo.dev.auto;

import org.springframework.stereotype.Repository;

@Repository("ms")
public class MySQL implements DataBase {
  @Override
  public void getConnection() {
    System.out.println("MySQL 연결");
  }
  @Override
  public void disConnection() {
    System.out.println("MySQL 연결 해제");
  }
}

 

 

앞서 본 것과 마찬가지로 <context:component-scan> 태그를 이용해 패키지 내의 모든 클래스를 자동으로 등록해 준다.

 

app.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: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-4.3.xsd">
	<context:component-scan base-package="doodoo.dev.auto"></context:component-scan>
</beans>

 

그리고 메인함수가 있는 MainClass에서 해당 데이터베이스를 불러와 보자.

 

같은 인터페이스를 구현한 클래스가 유일하지 않을 때 @Autowired 어노테이션만 작성하게 되면,
그 다수의 클래스 중 어느 것을 자동으로 주입해 줄 지 결정하지 못한다.
따라서 @Qualifier 어노테이션을 하나 더 붙여 원하는 데이터베이스를 의미하는 아이디를 입력해 주면
해당 아이디에 맞는 클래스 객체 주소를 불러와 적절하게 주입해 준다!

 

MainClass.java

package doodoo.dev.auto;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.stereotype.Component;

@Component("mc")
public class MainClass {
  @Autowired
  @Qualifier("ms")
  private DataBase db; //ms와 ora로 등록된 두 개의 bean이 있기 때문에.. 둘중에 뭐를 요청한건지 @Qualifier로 명시해 주어야 한다.
  //Autowired는 같은 게 있을 때.. 특정 객체를 지정할 수 없다.
  public static void main(String[] args) {
    ApplicationContext app = new ClassPathXmlApplicationContext("app.xml");
    MainClass mc = (MainClass) app.getBean("mc");
    mc.db.getConnection();
    mc.db.disConnection();
  }
}

클래스 메모리 할당

@Component, @Repository, @Service, @Controller, @RestController, @ControllerAdvice

생성된 객체 주소값을 받을 경우(XML/어노테이션 중심)

@Autowired, @Qualifier(""), @Inject

 

 

XML + Annotation으로 의존성 주입 (가장 많이 쓰임)

 

이번에는 자바 파일에 데이터베이스 연결 정보를 그대로 저장하지는 않고

XML 파일과  db.properties 파일에 따로 분리하면서,

패키지 채로 클래스를 불러와 메모리 할당은 어노테이션으로 지정해주는 방식으로 DI 를 구현해보자.

 

어떤 걸 쓸지 정도만 다르지 하는 방법은 다 똑같슈~

 

Config.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
	<typeAliases>
		<typeAlias type="doodoo.dev.xmlanno.MovieVO" alias="MovieVO"/>
	</typeAliases>
	<mappers>
		<mapper resource="doodoo/dev/xmlanno/movie-mapper.xml"/>
	</mappers>
</configuration>

 

app.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:context="http://www.springframework.org/schema/context"
	xmlns:p="http://www.springframework.org/schema/p"
	xmlns:util="http://www.springframework.org/schema/util"
	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-4.3.xsd
		http://www.springframework.org/schema/util 
		http://www.springframework.org/schema/util/spring-util-4.3.xsd">
<!-- 
사용자 정의 클래스 : 어노테이션(개별/나눠서 사용하는 부분)
라이브러리 클래스 : XML(공통으로 사용하는 부분)
-->
	<context:component-scan base-package="doodoo.dev.xmlanno"/>
<!-- 
***없는건 아직 안배워서 설정 못함
1. AOP 적용
***2. 사용자 정의 클래스 등록
***3. DataSource 설정
4. 트랜잭션 적용
***5. MyBatis, JPA 등록
6. 보안
7. WebSocket
 -->
	<!-- myBatis 연결 +보안! 연결정보를 따로 파일(db.properties)에 저장 -->
	<!-- 1.정보 읽기 (src/main/java 여기를 classpath라고 함)-->
	<util:properties id="db" location="classpath:db.properties"></util:properties>
	<!-- 2.정보를 모아서 mybatis로 전송 : BasicDataSource가 데이터베이스 연결 정보를 다 갖고있음! -->
	<bean id="ds" class="org.apache.commons.dbcp.BasicDataSource"
	 p:driverClassName="#{db['driver']}"
	 p:url="#{db['url']}"
	 p:username="#{db['username']}"
	 p:password="#{db['password']}"
	/>
	<!-- 3.myBatis = SqlSessionFactoryBean이 받아서 연결과 해제를 만든다 -->
	<bean id="ssf" class="org.mybatis.spring.SqlSessionFactoryBean"
	 p:dataSource-ref="ds"
	 p:configLocation="classpath:Config.xml"
	/>
</beans>

 

MovieDAO.java(Class)

package doodoo.dev.xmlanno;

import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.support.SqlSessionDaoSupport;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;
import java.util.*;

@Repository
public class MovieDAO extends SqlSessionDaoSupport {
  public List < MovieVO > movieListData(Map map) {
    //엄청 간단~~~~~ 
    return getSqlSession().selectList("movieListData", map);
  }

  @Autowired //ssf을 받아와서 DAO가 작동할 수 있도록 해 준다
  public void setSqlSessionFactory(SqlSessionFactory sqlSessionFactory) {
    super.setSqlSessionFactory(sqlSessionFactory);
  }
}

 

 

MainClass에서 DAO를 스프링을 통해 받을 것인지, 직접 지정해서 받을 지 지정할 수 있다.

 

1. getBean()으로 직접 받기

MainClass.java (Class)

package doodoo.dev.xmlanno;
import java.util.*;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class MainClass {
  public static void main(String[] args) {
    ApplicationContext app = new ClassPathXmlApplicationContext("app3.xml");
    Map map = new HashMap();
    map.put("start", 1);
    map.put("end", 20);
    //스프링에서 받아올 건지(Autowired) 우리가 직접 달라고 할 건지 정해야 함
    MovieDAO dao = (MovieDAO) app.getBean("movieDAO"); 
    //@Repository안에 id가 부여되어 있지 않음 -> 디폴트 아이디 = 맨앞글자 소문자
    List < MovieVO > list = dao.movieListData(map);
    for (MovieVO vo: list) {
      System.out.println(vo.getMno() + "." + vo.getTitle());
    }
  }
}

 

2. @Autowired를 통해 스프링에서 dao를 받아와 사용

MainClass.java(Class)

package doodoo.dev.xmlanno;
import java.util.*;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.stereotype.Component;
@Component("mc")
public class MainClass {
  @Autowired
  private MovieDAO dao;
  public static void main(String[] args) {
    ApplicationContext app = new ClassPathXmlApplicationContext("app3.xml");
    Map map = new HashMap();
    map.put("start", 1);
    map.put("end", 20);
    MainClass mc = (MainClass)app.getBean("mc");
    List < MovieVO > list = mc.dao.movieListData(map);
    for (MovieVO vo: list) {
      System.out.println(vo.getMno() + "." + vo.getTitle());
    }
  }
}

 

 

 

XML없이 java로 Config 만들기 (Spring5버전)

Config.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
	<typeAliases>
		<typeAlias type="doodoo.dev.spring5.MovieVO" alias="MovieVO"/>
	</typeAliases>
	<mappers>
		<mapper resource="doodoo/dev/spring5/movie-mapper.xml"/>
	</mappers>
</configuration>

 

MovieConfig.java (Class)

package doodoo.dev.spring5;

import javax.sql.DataSource;
import org.apache.commons.dbcp.BasicDataSource;
import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.ClassPathResource;

/*
 * xml 대신! 자바로 환경설정을 한다
 * Spring5는 순수 자바로만 생성하도록 한다.
 */
@Configuration //붙여주어야 함
@ComponentScan(basePackages = {
  "doodoo.dev.spring5"
}) //xml의 태그를 어노테이션화! 
//app.xml의 <context:component-scan base-package="doodoo.dev.spring5"/> 를 대체함
public class MovieConfig {
  @Bean("ds") //<bean id="">를 대체함
  public DataSource dataSource() {
    BasicDataSource ds = new BasicDataSource();
    ds.setDriverClassName("oracle.jdbc.driver.OracleDriver"); // p:driverClassName=""
    ds.setUrl("jdbc:oracle:thin:@localhost:1521:XE"); //p:url=""
    ds.setUsername("username"); //p:username=""
    ds.setPassword("password"); //p:password=""
    return ds;
  }
  @Bean("ssf")
  public SqlSessionFactory sqlSessionFactory() throws Exception {
    SqlSessionFactoryBean ssf = new SqlSessionFactoryBean();
    ssf.setDataSource(dataSource());
    ssf.setConfigLocation(new ClassPathResource("Config.xml")); //classpath:...와 같음
    return ssf.getObject();
  }
  //이제 DAO가 ssf를 받아줄 건데... -> MovieDAO에서!
}

 

 

MovieDAO.java (Class)

package doodoo.dev.spring5;

import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.support.SqlSessionDaoSupport;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;
import java.util.*;

@Repository
public class MovieDAO extends SqlSessionDaoSupport {
  //SqlSessionFactory를 받아주는 부분
  @Autowired //MySqlSessionFactoryBean에서 받아온 값을 여기에 채워넣어달라
  public void setSqlSessionFactory(SqlSessionFactory sqlSessionFactory) {
    super.setSqlSessionFactory(sqlSessionFactory);
  }

  public List < MovieVO > movieListData(Map map) {
    //엄청 간단~~~~~ 
    return getSqlSession().selectList("movieListData", map);
  }
}

 

여기서도 마찬가지로! 스프링을 통해 받아올 것인지, 직접 지정해서 받아올 것인지 정할 수 있다.

 

 

 

MainClass.java(Class)

이 때는 app을 가져올 때 ClassPathXmlApplicationContext가 아니라!

AnnotationConfigApplicationContext로 가져와야 한다! 

package doodoo.dev.spring5;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.stereotype.Component;

import java.util.*;
@Component
public class MainClass {
  public static void main(String[] args) {
    AnnotationConfigApplicationContext app
      = new AnnotationConfigApplicationContext(MovieConfig.class);
    MovieDAO dao = app.getBean("movieDAO",MovieDAO.class); //ID지정하지 않았으니 디폴트
    //getBean("ID",클래스형) => 형변환 수동으로 해 줄 필요 없다.
    Map map = new HashMap();
    map.put("start", 1);
    map.put("end", 100);
    MainClass mc = (MainClass) app.getBean("mainClass");
    List < MovieVO > list = mc.dao.movieListData(map);
    for (MovieVO vo: list) {
      System.out.println(vo.getMno() + "." + vo.getTitle());
    }
  }
}

MainClass.java(Class)

package doodoo.dev.spring5;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.stereotype.Component;

import java.util.*;
@Component
public class MainClass {
  @Autowired
  private MovieDAO dao;
  public static void main(String[] args) {
    AnnotationConfigApplicationContext app
      = new AnnotationConfigApplicationContext(MovieConfig.class);
    //		MovieDAO dao = app.getBean("movieDAO",MovieDAO.class); //ID지정하지 않았으니 디폴트
    //getBean("ID",클래스형) => 형변환 수동으로 해 줄 필요 없다.
    Map map = new HashMap();
    map.put("start", 1);
    map.put("end", 100);
    MainClass mc = (MainClass) app.getBean("mainClass");
    List < MovieVO > list = mc.dao.movieListData(map);
    for (MovieVO vo: list) {
      System.out.println(vo.getMno() + "." + vo.getTitle());
    }
  }
}

 

'부트캠프(END) > -Spring' 카테고리의 다른 글

Spring에 lombok 라이브러리 추가하기  (0) 2022.08.23
Spring 기초 : 기본 정보 - 수정중  (0) 2022.08.22
Spring 설치  (0) 2022.08.19

댓글()