학습하며 정리한 내용을 올리는 것이니, 참고용으로만 봐 주시길 바랍니다.
자바 스프링 프레임워크(renew ver.) - 신입 프로그래머를 위한 강좌

데이터베이스

: (시스템계정) system / root
: sqlplus
: create user root idientified by root;
: grant connect, resource to root;
: exit
: show user
: drop user root cascade; (system 계정에서 실행)

CREATE TABLE member (
    memId VARCHAR2(10) CONSTRAINT memId_pk PRIMARY KEY,
    memPw VARCHAR2(10),
    memMail VARCHAR2(15),
    memPurcNum NUMBER(3) DEFAULT 0 CONSTRAINT memPurNum_ck CHECK (memPurcNum < 3)
);

INSERT INTO member (memId, memPw, memMail) values ('b', 'bb', 'bbb@gamil.com');

SELECT * FROM member;

DELETE FROM member WHERE memId = 'b';

DROP TABLE member;

commit;

JDBC

: 드라이버 로딩 -> DB 연결 -> SQL 작성 및 전송 -> 자원 해제

// MemberDao.java

private String driver = "oracle.jdbc.driver.OracleDriver";
private String url = "jdbc:oracle:thin:@localhost:1521:xe";
private String userid = "root";
private String userpw = "root";

private Connection conn = null;
private PreparedStatement pstmt = null;
private ResultSet rs = null;

public int memberInsert(Member member) {
    int result = 0;

    try {
        // Driver 로딩
        Class.forName(driver); 

        // DB 연결
        conn = DriverManager.getConnection(url, userid, userpw);

        // Query 전송
        String sql = "INSERT INTO member (memId, memPw, memMail) values (?, ?, ?)";
        pstmt = conn.preparedStatement(sql);
        pstmt.setString(1, member.getMemId());
        pstmt.setString(2, member.getMemPw());
        pstmt.setString(3, member.getMemMail());
        result = pstmt.executeUpdate();

    } catch (ClassNotFoundException e) {
        e.printStackTrace();
    } catch (SQLException e) {
        e.printStackTrace();
    } finally { // 자원 해제
        try {
            if (pstmt != null) pstmt.close();
            if (conn != null) conn.close();
        } catch (SQLException e) {
            e.printStackTrace();
        }   
    }
    return result;
}

public Member memberSelect(Member member) {
    Member mem = null;
    try {
        // Driver 로딩
        Class.forName(driver);

        // DB 연결
        conn = DriverManager.getConnection(url, userid, userpw);

        // Query 전송
        String sql = "SELECT * FROM member WHERE memId = ? AND memPw = ?";
        pstmt = conn.preparedStatement(sql);
        pstmt.setString(1, member.getMemId());
        pstmt.setString(2, member.getMemPw());
        rs = pstmt.executeUpdate();

        while (rs.netx()) {
            String memId = rs.getString("memid);
            String memPw = rs.getString("mempw);
            ...

            mem = new Member();
            mem.setMemId(memId);
            ...

        }
    } catch (Exception e) {
        ...
    } finally { // 자원해제
        try {
            if (rs != null) rs.close();
            if (pstmt != null) pstmt.close();
            if (conn != null) conn.close();
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }

    return mem;
}

: 매번 Driver 로딩, DB 연결, 자원 해제를 해 주어야 한다는 단점 존재한다. 이를 간편하게 하기위해 JdbcTemplate을 사용한다.

JDBC Template 사용

: JDBC 사용시 Driver 로딩, DB 연결, 자원 해제를 JDBC Template에서 자동으로 해 주고, 각각의 함수에서는 SQL Query문만 작성해서 실행해주면 된다.

// pom.xml

<!-- DB -->
<dependency>
    <groupId>com.oracle</groupId>
    <artifactId>ojdbc6</artifactId>
    <version>12.1.0.2</version>
</dependency>
<dependency>                            // 스프링 JDBC 추가
    <groupId>org.springframework</groupId>
    <artifactId>spring-jdbc</artifactId>
    <version>4.1.6.RELEASE</version>
</dependency>
<dependency>                            // 추가
    <groupId>com.mchange</groupId>
    <artifactId>c3p0</artifactId>
    <version>0.9.5</version>
</dependency>
// MemberDao.java

public class MemberDao implements IMemberDao {

    private DriverManagerDataSource dataSource;
    private JdbcTemplate template;

    /*
    private Connection conn = null;
    private PreparedStatement pstmt = null;
    private ResultSet rs = null;
    */

    public MemberDao() {
        /* c3p0 의 DriverManagerDataSource 사용 */
        dataSource = new DriverManagerDataSource();
        dataSource.setDriverClass(dirver); //  드라이버 로딩
        dataSource.setJdbcUrl(url); // DB 연결
        dataSource.setUser(userid);
        dataSource.setPassowrd(iserpw);

        /* spring의 DriverManagerDataSource 사용
        dataSource = new DriverManagerDataSource();
        dataSource.setDriverClassName(dirver); 
        dataSource.setUrl(url); 
        dataSource.setUsername(userid);
        dataSource.setPassowrd(iserpw);
        */

        template = new JdbcTemplate(); // JDBC Template 사용
        template.setDataSource(dataSource);
    }
}

public int memberInsert(Member member) {
    int result = 0;

    String sql = "INSET INTO member (memId, memPw, memMail) values (?, ?, ?)";

    // 1st 방법
    result = template.update(sql, member.getMemId(), ...);

    /*
    // 2nd 방법 (이 때에는, sql문이 외부에서 사용될 수 있으므로 final로 선언해야한다 > final String sql)
    result = template.update(new PreparedStatementCreator() {
        @Override
        public PreparedStatement createPreparedStatement(Connection conn) throws SQLException {
            PreparedStatement pstmt = conn.prepareStatement(sql);
            pstmt.setString(1, member.getMemId());
            ...

            return pstmt;
        }
    });

    // 3rd 방법 (이 때에는, sql문이 외부에서 사용될 수 있으므로 final로 선언해야한다 > final String sql)
    result = template.update(sql, new PreparedStatementSetter()) {
        @Override
        public void setValues(PreparedStatement pstmt) throws SQLException {
            pstmt.setString(1, member.getMemId());
            ...
        }
    });
    */

    return result;
}

public Member memberSelect(Member memeber) {
    List<Member> members = null;

    String sql = "SELECT * FROM member WHERE memId = ? AND memPw = ?";

    // 1st
    members = template.query(sql, new PreparedStatementSetter() {
        @Override
        public void setValues(PreparedStatement pstmt) throws SQLException {
            pstmt.setString(1, member.getMemId());
            pstmt.setString(2, member.getMemPw());
        }
    }, new RowMapper<Member>() {
        @Override
        public Member mapRow(ResultSet rs, int rowNum) throws SQLException {
            Member mem = new Member();

            mem.setMemId(rs.getString("memId"));
            ...

            return mem;
        }
    });

    if (member.isEmpty()) return null;

    /*
    // 2nd
    members = template.query(new PreparedStatementCreator() {

        @Override
        public PreparedStatement createPreparedStatement(Connection conn)
                throws SQLException {
            PreparedStatement pstmt = conn.prepareStatement(sql);
            pstmt.setString(1, member.getMemId());
            pstmt.setString(2, member.getMemPw());
            return pstmt;
        }
    }, new RowMapper<Member>() {

        @Override
        public Member mapRow(ResultSet rs, int rowNum) throws SQLException {
            Member mem = new Member();
            mem.setMemId(rs.getString("memId"));
            mem.setMemPw(rs.getString("memPw"));
            mem.setMemMail(rs.getString("memMail"));
            mem.setMemPurcNum(rs.getInt("memPurcNum"));
            return mem;
        }
    });

    // 3rd
    members = template.query(sql, new RowMapper<Member>() {

        @Override
        public Member mapRow(ResultSet rs, int rowNum) throws SQLException {
            Member mem = new Member();
            mem.setMemId(rs.getString("memId"));
            mem.setMemPw(rs.getString("memPw"));
            mem.setMemMail(rs.getString("memMail"));
            mem.setMemPurcNum(rs.getInt("memPurcNum"));
            return mem;
        }

    }, member.getMemId(), member.getMemPw());

    // 4th
    members = template.query(sql, new Object[]{member.getMemId(), member.getMemPw()}, new RowMapper<Member>() {

        @Override
        public Member mapRow(ResultSet rs, int rowNum) throws SQLException {
            Member mem = new Member();
            mem.setMemId(rs.getString("memId"));
            mem.setMemPw(rs.getString("memPw"));
            mem.setMemMail(rs.getString("memMail"));
            mem.setMemPurcNum(rs.getInt("memPurcNum"));
            return mem;
        }

    });
    */

    return members.get(0);
}

커넥션풀

: 다수의 사용자가 DB 접속 시 드라이버를 로딩하고, 커넥션을 만드는 작업은 메모리를 상당히 많이 차지하고 이는 서버에 상당한 부하를 줄 수 있다. 따라서 사용자 요청이 들어오지 않아도 미리 커넥션을 만들어 놓고 요청 있을 때 미리 만들어 놓은 것을 이용하는 방법.
: c3p0모듈의 ComboPooledDataSource를 사용
: 사용방법은 이전(public MemberDao() { ... })과 동일. 하지만,

dataSource = new ComboPooledDataSource();
try {
    dataSource.setDriverClass(driver);
    ...
} catch (PropertyVetoException e) {
    e.printStackTrace();
}

와 같이 try-catch 문을 사용해 주어야 한다.

학습하며 정리한 내용을 올리는 것이니, 참고용으로만 봐 주시길 바랍니다.
자바 스프링 프레임워크(renew ver.) - 신입 프로그래머를 위한 강좌

세션 & 쿠키

  1. 세션 생성
public String memLogin(Member member, HttpServletRequest request) {
    ...
    HttpSession session = request.getSession();
    session.setAttribute("member", mem);
    return "/member/loginOk";
}

public String memLogin(Member member, HttpSession session) {
    ...
    session.setAttribute("member", mem);
    return "/member/loginOk";
}

1.1 세션 회원정보 수정

public ModelAndView modifyForm(HttpServletRequest request) {
    HttpSession session = request.getSession();
    Member member = session.getAttribute("member");

    ModelAndView mav = new ModelAndView();
    mav.addObject("member", service.memberSearch(member));
    ...
  1. 세션 삭제
public String memLogout(Member member, HttpSession session) {
    ...
    session.invalidate();
    return "/member/logout ";
}

세션 주요 메소드

  • getId(): 세션 ID 반환
  • setAttribute(): 세션 객체에 속성을 저장
  • getAttribute(): 세션 객체에 저장된 속성을 반환
  • removeAttribute(): 세션 객체에 저장된 속성 제거
  • setMaxInactiveInterval(): 세션 객체의 유지 시간 설정
  • `get ~
  • invalidate(): 세션 객체의 모든 정보삭제
  1. 쿠키 생성
public String mallMain(Mall mall, HttpServletResponse) {
    Cookie genderCookie = new Cookie("gende", mall.getGender());

    if (mall.isCookieDel()) {
        genderCookie.setMaxAge(0);
        mall.setGender(null);
    } else {
        genderCookie.setMaxAge(60 * 60);
    }
    response.addCookie(genderCookie);
    return "/mall/main";
  1. 쿠키 사용
@public String mallIndex(Mall mall, @CookieValue(value="gende", required=false) Cookie genderCookie, HttpServletRequest request) {
    if (genderCookie != null)
        mall.setGender(genderCookie.getValue());
    return "/mall/index";
}
}

리다이렉트 & 인터셉터

리다이렉트

: reutrn "redirect:/page";
:

public ModelAndView removeForm(HttpServletRequest request) {
    ModelAndView mav = new ModelAndView();
    ...
    if (null == member) {
        mav.setViewName("redirect:/");
    } else {
        mav.addObject("member", member);
        mav.setViewName("/member/removeForm");
    }

    return mav;
}

인터셉터

: 리다이렉트를 사용해야 하는 경우가 많을 때 HandlerInterceptor를 이용할 수 있다.

--------------- ###########################
--------------- # ------ Request -------- #
--------------- ###########################
--------------------------- |
--------------- ###########################
--------------- #--- DispatcherServlet ---#
--------------- ###########################
--------------------------- |
#######################################################
#---------- HandlerInterceptor(인터페이스) ------------#
#-----------------------------------------------------#
# PreHandle()------PostHandler()-----afterCompletion()#
#######################################################
------ | -------------- ^ ----- | --------- ^
------ | -------------- | ----- | --------- |
--- ######################## -- | --------- |
--- #  Handler(Controller) # -- | --------- |
--- ######################## -- |  #####################
------------------------------- ㄴ># ------ View ----- #
---------------------------------- #####################
        
#######################################################
# ---------------------- Response ------------------- #
#######################################################
  • preHandle(): Controller가 작업하기 전 작업한다. 리다이렉트를 대체 가능하다. 주로 쓰인다.
  • postHandle(): Controller가 작업한 후 작업한다.
  • afterCompletion(): Controller 와 View가 작업한 후에 작업한다.

: 주로 HandlerInterceptor 인터페이스를 구현하기 보다는, 이들이 구현되어 있는 HandlerInterceptorAdapter 클래스를 상속받아 사용한다.

public class MemberLoginInterceptor extends HandlerInterceptorAdaptor {

    @Override
    public bollean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        HpptSession session = request.getSession(false);
        if (session != null) {
            return true;
        }

        response.sendRedirect(request.getContextPath() + "/"); // main 페이지로 보낸다
        return false;
    }
}
// servlet-context.xml
// 스프링 설정파일

<interceptors>
    <interceptor>
        <mapping path="/member/modifyForm" /> // 
        <mapping path="/member/removeForm" /> // 이곳으로 요청이 들어왔을 때 
        <beans:bean class="com.bs.lec21.member.MemberLoginInterceptor" /> // 이 인터셉터가 동작을 해라
    </interceptor>
</interceptors>
<mapping path="/member/**" /> // 멤버 하위의 모든 경로에 대해 동작을 하는데
<exclude-mapping path="/member/joinForm" /> // 여기는 제외해라
<exclude-mapping path="/member/join" />
<exclude-mapping path="/member/login" />

'Backend > Spring' 카테고리의 다른 글

Spring - 데이터베이스  (0) 2021.02.14
Spring - MVC  (0) 2021.02.04
Spring - 스프링 컨테이너의 생성관련  (0) 2021.02.02
Spring - Bean과 의존객체 주입  (0) 2021.02.01
Spring - Dependency Injection  (0) 2021.01.31

학습하며 정리한 내용을 올리는 것이니, 참고용으로만 봐 주시길 바랍니다.
자바 스프링 프레임워크(renew ver.) - 신입 프로그래머를 위한 강좌

MVC를 이용한 웹 서비스

  1. MVC의 기본 구조: M1 구조에 비해 유지보수 및 기능개선에 이점

    브라우저 <-> Controller - Service - DAO <- (Model) -> DB
                 |
                View
    .
    Controller: 이것들을 Control(기능, 뷰 등을 Control)
    Service: 기능
    View: 사용자에게 보여주는 부분
    Dao: DB와 연동 
  2. 스프링 MVC 프레임워크 구조

               HandlerMapping   HandlerAdapter <-> Controller
                     |           / 
    브라우저 <-> DispatcherServlet <
                     |           \
                    View         ViewResolver

    2.1. 클라이언트가 브라우저를 통해 요청을 보내면 DispatcherServlet이 받는다.
    2.2. DispatcherServlet은 이를 HandlerMapping에게 보내 가장 적합한 Controller를 찾아준다.
    2.3. DispatcherServlet은 HandlerAdapter에게 요청을 보내고 HandlerAdapter는 HandlerMapping이 찾아준 Controller 객체 아래에 있는 메소드들 중 가장 적합한 메소드가 무엇인지 찾아준다. 그 후, 처리된 결과를 Model(View 포함)이라는 데이터를 가지고와서 DispatcherServlet에게 건네준다.
    2.4. 결과(?Model?, View)를 가지고 DispatcherServlet은 ViewResolver에게 보내 View에 해당하는 가장 적합한 JSP 문서를 찾아달라고 요청하여, ViewResolver는 View를 선택해준다.
    2.5. 찾아진 JSP가 있는 View에게 가서 응답(JSP)을 클라이언트에게 보내 주도록 한다.

  3. DispatcherServlet 설정하기

    // WEB-INF/web.xml
    //
    <servlet>
     <servlet-name>appServlet</servlet-name> // 서블릿 별칭
     <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> // 서블릿명(패키지 이름을 포함한 전체 서블릿 명)
     <init-param> // 초기 파라미터
         <param-name>contextConfigLocation</param-name>
         <param-value>/WEB-INF/spring/appServlet/servlet-context.xml</param-value> // 스프링 설정파일 (DispatcherServlet이 등록될 때 스프링 설정파일까지 설정해 주도록 함)
     </init-param>
     <load-on-startup>1</load-on-startup>
    </servlet>
    //
    <servlet-mapping>
     <servlet-name>appServlet</servlet-name> // 위에서 별칭으로 지정한 appServlet이
     <url-pattern>/</url-pattern> // root(/)로 들어오는 모든 요청을 처리하도록
    </servlet-mapping>
    • DispatcherServlet 설정 시 위의 초기 파라미터(init-param)에서 지정한 파일을 이용해 스프링 컨테이너를 생성한다. 초기 파라미터를 지정하지 않은 경우 서블릿별칭(appServlet-context.xml)(이 파일이 존재해야함.)을 이용해 스프링 컨테이너를 생성한다.
    • 이를 통해 HandlerMapping, HandlerAdapter, ViewResolver가 생성된다.
    1. Controller 객체
      1. Controller 생성 방법
    // servlet-context.xml
    //
    <annotation-driven /> // 스프링 컨테이너 사용을 위한 부가적인 클래스들이 빈 객체로 스프링 설정파일에 등록됨.
    // Controller 객체로 사용할 클래스 정의
    //
    @Controller
    public class HomeController {
      ...
    }

    4.2. @RequestMapping
    :사용자로부터 들어오는 요청을 Controller가 메소드로 맵핑

    http://localhost:8090/ch08/success (ch08: project path?name?)
    //
    @RequestMapping("/success")
    public String success(Model model) {
     return "success";
    }

    4.3. Model 타입의 파라미터
    : Controller는 Model 객체에 데이터를 담아 DispatcherServlet에 전달

    @RequestMapping("/success")
    public String success(Model model) {
     model.setAttribute('tempData', "model has data");
    //
     return "success";
    }

    4.3. view 객체
    : 스프링 설정파일에 ViewResolver를 생성

    <beans:bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
     <beans:property name="prefix" value="/WEB-INF/views/" />
     <beans:property name="suffix" value=".jsp" />
    </beans:bean>
    @RequestMapping("/success")
    public String success(Model model) {
     return "success";
    }

    : return값의 success 앞뒤로 ViewResolver의 prefix, suffix를 붙여주어 /WEB-INF/views/success.jsp 라는 View를 만들어준다.

스프링 MVC 웹 서비스 파일의 구성

  1. web.xml

    • DispatcherServlet을 등록한다.
    • 사용자의 모든 요청을 받기 위해 서블릿 맵핑 경로를 /로 설정한다.
  2. servlet-context.xml

    • DispatcherServlet을 서블릿으로 등록할 때 contextConfigLocation이라는 초기화 파라미터를 servlet-context.xml로 지정하고 있었다.
    • 이는 스프링 설정파일이다.
    • 클래스로부터 객체(bean)을 생성하고 조립하는 역할을 한다.
    • 웹 구동을 위한 resource(jsp, html, css) 등을 맵핑해 준다.
    • InternalResourceViewResolver의 prefix, suffix를 정의하여 View로써 response를 응답하도록 해 준다.

Service Annotation

: 스프링 설정파일(servlet-context.xml)에 Bean 객체를 생성하지 않아도, 서비스 객체마다 @Service Annotation을 붙여주면 자동으로 스프링 컨테이너에 담겨지고, Controller에서 @Autowired만 붙여주면 자동으로 서비스 객체를 사용할 수 있음.
: @Component, Repository
: Dao 또한 동일하게 사용가능
: @Repository("memService"), @Repository(name="memService") 와 같이 key-value 형식으로 특정 이름을 지정할 수 있으나 권장되진 않음.

HttpServletRequest 대신 RequestParam 사용하기

@RequestMapping(value="/memLogin", method=RequestMethod.POST)
// public String memLogin(Model model, HttpServletRequest request) {
public String memLogin(Model model, @RequestParam("memId") String memId, @RequestParam("memPw") String memPw) {    
//    String memId = request.getParameter("memId");
//    String memPw = request.getParameter("memPw");
//    
    Member member = service.memberSearch(memId, memPw);
<form action="/lec17/memLogin" method="post">
    ID : <input type="text" name="memId" ><br>
    PW : <input type="password" name="memPw" ><br>
    <input type="submit" value="Login" >
</form>
  • @RequestParam(value="memPW", required=false, defaultValue="1234") 와 같이 필수로 넘겨주어야 하는지 여부, default 값 을 설정할 수 있다. 잘 사용되지는 않는다.

커맨드 객체를 이용한 HTTP 정보 얻어오기

// public String memJoin(Model model, HttpServletRequest request) {
public String memJoin(Member member) {
//
//  String memId = request.getParameter("memId");
    ...
//    
//    service.memberRegister(memId, ...);
    service.memberRegister(member.getMemId(), ...);

//    model.addAttribute("memId", memId);
      ...
//
    return "memJoinOk";
    <h1> memJoinOk </h1>
//  ID : ${memId}<br />
    ID : ${member.memId}<br />
    ...

MemberAttribute 사용하기

  1. 기존의 커맨드 객체를 이용하는 방식에서 커맨드 개체의 변수명을 사용하는 것이 아니라 닉네임을 사용할 수 있도록 한다.
    public String memJoin(Member member)
    -> ${member.memId}

    public String memJoin(@ModelAttribute("mem") Member member)
    -> ${mem.memId}

  2. 함수 위에 @ModelAttribute("serverTime")을 지정하면, 다른 함수가 호출되어도 항상 @ModelAttribute를 지정한 함수도 같이 호출된다.

    @ModelAttribute("serverTime")
    public String getServerTime(Locale locale) {
     ...
    }
    //   
    @RequestMapping(value="/memJoin", method=RequestMethod.POST) {
     ...
    }

    Model & ModelAndView

    : Model을 뷰에 데이터만을 전달하기 위한 객체이고,
    ModelAndView는 데이터와 뷰ㅜ의 이름을 함께 전달하는 객체이다.

    ////////// Model
    public String memModify(Model model, Member member) {
     ...
     model.addAttribute("memBef", value);
     return "memModifyOk";
    }
    //
    ///////// ModelAndView
    public ModelAndView memModify(Member member) {
     ...
     ModelAndView mav = new ModelAndView();
     mav.addObject("memBef", value);
     mav.setViewName("memModifyOk");
    //    
     return mav;
    }

학습하며 정리한 내용을 올리는 것이니, 참고용으로만 봐 주시길 바랍니다.
자바 스프링 프레임워크(renew ver.) - 신입 프로그래머를 위한 강좌

스프링컨테이너 생명주기

  1. 생성: 스프링컨테이너와 빈 객체들이 생성되고 주입(의존관계)된다.
GenericXmlApplicationContext ctx = new GenericXmlApplicationContext("classpath:appCtx.xml");
  1. 사용
    : `BookRegisterService bookRegisterService = ctx.getBean("bookRegisterService", BookRegisterService.class);

  2. 소멸
    : ctx.close();

Bean 객체 생성/제거 시 특정작업을 수행하도록 하기

: 해당 객체가 인증절차(DB연결, 어떤 작업으로 인한인증작업) 시 주로 사용된다.

  1. 인터페이스 이용하기
public class BookRegisterService implements InitializingBean, DisposableBean {

    @Autowired 
    private BookDao bookDao;

    @Override
    public void afterPropertiesSet() throws Exception {
        System.out.prinltn("Bean 객체 생성 시");
    }

    @Override
    public void destory() throws Exception {
        System.out.println("Bean 객체 소멸 시");
    }
}
  • InitializingBean, DisposableBean 인터페이스를 상속받는다.
  • 상속받은 인터페이스의 afterPropertiesSet, destory 함수를 구현한다.
  1. 스프링 속성 이용하기
<bean id="memberRegisterService" class="com.member.dao.MemberRegisterService" init-method="initMethod" destroy-method="destroyMethod" />
...
public class MemberRegisterService {
    ...
    public void initMethod() {

    }

    public void destroyMethod() {

    }
}
  • bean 태그에 init-method, destroy-method 속성과 함수 이름을 넣어준다.
  • 해당 Class에 init, destroy 함수를 구현해 준다.

XML 파일이 아닌 Java를 이용해 스프링 설정하기

  • applicationContext.xml -> MemberConfig.java

  • 이 자바 클래스 파일(MemberConfig.java)이 스프링 설정파일로써 스프링 컨테이너를 만드는 데 사용될 것임을 명시 -> @Configuration

  • 이 메소드는 Bean객체를 만드는 데 사용될 것임을 명시 -> @Bean

  • 자바 클래스 파일 명세

@configuration
public class MemberConfig {
    /* 기본 Bean 객체 생성하기 */
    // <bean id="**studentDao**" class="*ems.member.dao.StudentDao*" />

    @Bean
    public *StudentDao* **studentDao**()  {
        return new StudentDao();
    }

    /* DI가 있는 Bean 객체 생성하기 */
    /*
    <bean id="registerService" class="ems.member.service.StudentRegisterService">
        <constructor-arg ref="studentDao"></constructor-arg>
    </bean>
    */

    @Bean
    public StudentRegisterService registerService() {
        return new StudentRegisterService(studentDao());
    }

    /* setter가 있는 Bean 객체 생성하기 */
    /*
    <bean id="dataBaseConnectionInfoDev" class="...DataBaseConnectionInfo">
        <property name="jdbcUrl" value="jdbc:oracle:...">
    </bean>
    */

    @Bean
    public DataBaseConnectionInfo dataBaseConnectionInfoDev() {
        DataBaseConnectionInfo infoDev = new DataBaseConnectionInfo();
        infoDev.setJdbcUrl("jdbc:oracle:...");

        return infoDev;
    }

    /* setter에 다른 Bean객체를 넣는? Bean 객체 생성하기 */
    /*
    <bean id="...">
        <property name="dbInfos">
            <map>
                <entry>
                    <key>
                        <value>name</value>
                    </key>
                    <value>Jay</value>
                </entry>
                <entry>
                    <key>
                        <value>dev</value>
                    </key>
                    <ref bean="dataBaseConnectionInfoDev" />
                </entry>
            </map>
        </property>
    */

    @Bean
    ...
    dbInfos.put("name", "Jay");
    dbInfos.put("dev", dataBaseConnectionInfoDev());
    info.setDbInfos(dbInfos);
}
  • 스프링 컨테이너 생성하기
/*
GenericXmlApplicationContext ctx =
    new GenericApplicationContext("classpath:applicationContext.xml");
*/

AnnotationConfigApplicationContext ctx = 
    new AnnotationConfigApplicationContext(MemberConfig.class);

Java 파일 분리

: DB관련 Dao, Service 객체, DB관련 기능, Utils 로 보통 분리한다.

  • 분리된 자바 파일은 다음과 같이 comma를 이용해 여러개를 불러올 수 있다.
    AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(MemberConfig1.class, MemberConfig2.class, MemberConfig3.class);
  • 또는, MemberConfig1.java 파일 내 @Import({MemberConfig2.class, MemberConfig3.class}) 를 기입해주고 MemberConfig1.class만 불러오면 된다.

'Backend > Spring' 카테고리의 다른 글

Spring - 데이터베이스  (0) 2021.02.14
Spring - 세션과 쿠키 && 리다이렉트와 인터셉트  (0) 2021.02.09
Spring - MVC  (0) 2021.02.04
Spring - Bean과 의존객체 주입  (0) 2021.02.01
Spring - Dependency Injection  (0) 2021.01.31

학습하며 정리한 내용을 올리는 것이니, 참고용으로만 봐 주시길 바랍니다.
자바 스프링 프레임워크(renew ver.) - 신입 프로그래머를 위한 강좌

스프링 설정파일(/src/main/resources/applicationContext.xml) 분리

  1. .

     String[] appCtxs = {"classpath:appCtx1.xml", "classpath:appCtx2.xml", "classpath:appCtx3.xml"};
     GenericXmlApplicationContext ctx = new GenericXmlApplicationContext(appCtxs);
  2. appCtxImport.xml 중

    <import resource="classpath:appCtx2.xml"/>
    <import resource="classpath:appCtx3.xml"/>
    GenericXmlApplicationContext ctx = 
    new GenericXmlApplicationContext("classpath:appCtxImport.xml");

Bean의 범위

: Bean은 기본적으로 Singleton의 개념이다.
: getBean("A") 를 하면 Spring Container에 생성되어있는 A 객체를 참조하는 값을 가지고 올 뿐 객체를 새롭게 생성하는 것은 아니다.
: Singleton 과 반대대는 Prototype의 개념도 있는데, 이 방식을 적용하기 위해서는
<bean id="~" class="" scope="prototype"> </bean>을 해 주어야한다. (흔치 않음)

의존객체 자동주입

: 기존에는 <constructor-arg>, <property> 태그를 이용해 의존객체를 명시하였다.
: @Autowired, @Resource 어노테이션을 이용해 스프링 컨테이너가 자동으로 필요한 의존대상 객체를 찾아 의존 대상 객체가 필요한 객체에 주입해준다.
: 스프링 컨테이너 설정파일에 <context:annotation-config />를 기입해 주어야 한다.

  1. @Autowired

    • 주입하려고 하는 객체의 타입이 일치하는 객체를 자동으로 주입
    • 생성자, property(member), method에 쓸 수 있음
    • @Autowired 구문을 보면, 해당 구문에 필요한 객체의 데이터 타입을 갖고있는 빈 객체를 찾아 넣어준다.
      • @Autowired public void wordConstructor(WordDao wordDao) {} > **WordDao** wordDao
      • <bean id = "wordDao" class="com.word.dao.WordDao" /> > class="com.word.dao.WordDao"
  2. @Resource

    • 주입하려고 하는 객체의 이름이 일치하는 객체를 자동으로 주입
    • property(member), method에만 쓸 수 있음
    • 이름: private WordDao wordDao; 에서 변수명(wordDao)
    • @Autowired public void wordConstructor(WordDao wordDao) {} > WordDao **wordDao**
    • <bean id = "wordDao" class="com.word.dao.WordDao" /> > id = "wordDao"

의존객체 선택

: 동일한 객체가 2개 이상인 경우 스프링 컨테이너는 자동 주입 대상 객체를 판단하지 못해 Exception을 발생시킴

<bean id="wordDao" class="com.word.dao.WordDao">
   <qualifier value="useDao" />
</bean>
<bean id="wordDao2" class="com.word.dao.WordDao" />
<bean id="wordDao3" class="com.word.dao.WordDao" />

...

@Autowired
@Qualifier("useDao")
private WordDao wordDao;

: 위 처럼 @Qualifier 어노테이션을 사용하면 해결이 된다.

  • bean 객체에 태그에 value를 할당해 주면, @Qualifier를 만났을 때 해당 value에 매칭되는 bean 객체를 넣어준다.
    : 단, bean 객체의 id와 객체의 이름(변수명)이 일치할 경우 @Qualifier를 쓰지 않아도 되긴한다. 하지만 혼동을 줄 수 있으니 @Qualifier를 쓰도록하자.

의존객체 자동주입 체크

@Autowired(required = false)
private WordDao wordDao;

: 의존객체가 존재하면 주입하고, 없으면 주입하지마!
: required = false를 이용하면, 스프링컨테이너에서 bean 객체를 만들지 않았을 때 Exception이 발생하는 상황을 제거해 줄 수 있음
: 선호되는 방식은 아님

@Inject

: @Autowired와 동일한 기능을 제공하는 것으로, 의존 객체를 자동으로 주입할 수 있다.
: 차이점은, required 속성을 제공하지 않는다.
: 차이점은, @Qualifier 대신 @Named를 쓰며, 스프링컨테이너에서 qualifier 태그를 쓸 필요 없다.
: Autowired가 일반적으로 더 많이 쓰인다.

<bean id="wordDao1" class="com.word.dao.WordDao" />
<bean id="wordDao2" class="com.word.dao.WordDao" />
<bean id="wordDao3" class="com.word.dao.WordDao" />

@Inject
@Named(value="wordDao1")
private WordDao wordDao;

'Backend > Spring' 카테고리의 다른 글

Spring - 데이터베이스  (0) 2021.02.14
Spring - 세션과 쿠키 && 리다이렉트와 인터셉트  (0) 2021.02.09
Spring - MVC  (0) 2021.02.04
Spring - 스프링 컨테이너의 생성관련  (0) 2021.02.02
Spring - Dependency Injection  (0) 2021.01.31

학습하며 정리한 내용을 올리는 것이니, 참고용으로만 봐 주시길 바랍니다.
자바 스프링 프레임워크(renew ver.) - 신입 프로그래머를 위한 강좌

Dependency Injection

  1. 생성자를 이용한 DI
<bean id="studentDao" class="ems.member.dao.StudentDao" ></bean>


    <bean id="registerService" class="ems.member.service.StudentRegisterService">
        **<constructor-arg ref="studentDao" ></constructor-arg>**
    </bean>

: src/main/resources/applicationContext.xml 파일에 <constructor-arg ref="studentDao" >를 이용해 의존성 주입

  1. setter를 이용한 DI
public class DataBaseConnectionInfo {

    private String jdbcUrl;
    private String userId;
    private String userPw;

    public String getJdbcUrl() {
        return jdbcUrl;
    }

    ...
<bean id="dataBaseConnectionInfoDev" class="ems.member.DataBaseConnectionInfo">
        <property name="jdbcUrl" value="jdbc:oracle:thin:@localhost:1521:xe" />
        <property name="userId" value="scott" />
        <property name="userPw" value="tiger" />
    </bean>

: <property name="jdbcUrl" value= ... /> 를 이용해 주입

  1. List 타입 DI 주입
public void setDevelopers(List<String> developers) {
        this.developers = developers;
}
<bean id="informationService" class="ems.member.service.EMSInformationService">
    <property name="developers">
            <list>
                <value>Cheney.</value>
                <value>Eloy.</value>
                <value>Jasper.</value>
                <value>Dillon.</value>
                <value>Kian.</value>
            </list>
        </property>
  1. Map 타입 DI

    <property name="administrators">
            <map>
                <entry>
                    <key>
                        <value>Cheney</value>
                    </key>
                    <value>cheney@springPjt.org</value>
                </entry>
                <entry>
                    <key>
                        <value>Jasper</value>
                    </key>
                    <value>jasper@springPjt.org</value>
                </entry>
            </map>
        </property>

    : 아래와 같이 value 위치에 bean 객체를 넣을 수 있음

    <entry>    
    <key>
        <value>dev</value>
    </key>
    <ref bean="dataBaseConnectionInfoDev"/>
    </entry>

+ Recent posts