[Spring] @Configuration로 Bean 생성하기

2023. 10. 18. 23:55학부 강의/웹프로그래밍 (Spring)


0. 출처

아직 배우고 있는 중이라 부정확한 정보가 포함되어 있을 수 있습니다!
주의하세요!

 

 

올인원 스프링 프레임워크 참고.

 

올인원 스프링 프레임워크 : 네이버 도서

네이버 도서 상세정보를 제공합니다.

search.shopping.naver.com

 


 

1. @Configuration

 

XML을 사용하지 않고 Java Code로 스피링 설정 파일을 만드는 방법에 대하여 알아보자.

 

가. MemberConfig

 

@Configuration annotation을 사용해서 스프링 프레임워크에서 MemberConfig 클래스를 스프링 설정 파일로 인식하게 한다.

 

applicationContext.xml을 모두 옮긴다.

 

<!--applicationContext.xml-->
<bean id="studentDao" class="ch06_pjt_01.ems.member.dao.StudentDao"/>

위 내용은 다음과 같이 옮길 수 있다.

 

package ch06_pjt_2.ems.configuration;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import ch06_pjt_01.ems.member.dao.StudentDao;

@Configuration
public class MemberConfig {

    @Bean
    public StudentDao studentDao() {
        return new StudentDao();
    }
}
  • @Configuration : MemberConfig라는 class에 추가한다. 이제 해당 class를 스프링 설정 파일로 인식하게 된다.
  • @Bean : bean을 추가한다.
  • public StudentDao studentDao() { : class는 StudentDao이고 id는 studentDao인 bean이 추가되었다. (id → 메서드 이름, class → 반환되는 데이터 타입)

 

@Configuration
@ComponentScan(basePackage = {"ch06_pjt_2","대충 탐색할 경로"})
public class MemberConfig {
  • @ComponentScan(basePackage = {"ch06_pjt_2","대충 탐색할 경로"})
    : 뿐만아니라 소스코드에서 @Component, @Controller, @Service, @Repository 등 annotation을 사용한 경우도 찾아서 Bean으로 등록한다.
    : 효율적인 탐색을 위해서 basePackage를 설정해 탐색 범위를 최적화할 수 있다.

 

나머지도 옮긴다.

package ch06_pjt_2.ems.configuration;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import ch06_pjt_01.ems.member.DBConnectionInfo;
import ch06_pjt_01.ems.member.dao.StudentDao;
import ch06_pjt_01.ems.member.service.EMSInformationService;
import ch06_pjt_01.ems.member.service.PrintStudentInformationService;
import ch06_pjt_01.ems.member.service.StudentAllSelectService;
import ch06_pjt_01.ems.member.service.StudentDeleteService;
import ch06_pjt_01.ems.member.service.StudentModifyService;
import ch06_pjt_01.ems.member.service.StudentRegisterService;
import ch06_pjt_01.ems.member.service.StudentSelectService;
import ch06_pjt_01.ems.utils.InitSampleData;

@Configuration
public class MemberConfig {

    @Bean
    public InitSampleData initSampleData() {
        InitSampleData initSampleData = new InitSampleData();

        String[] sNums = {"hbs001","hbs002","hbs003","hbs004","hbs005","hbs006"};
        initSampleData.setsNums(sNums);

        String[] sIds = {"rabbit","hippo","raccoon","elephant","lion","human"};
        initSampleData.setsIds(sIds);

        String[] sPws = {"p0001","p0002","p0003","p0004","p0005","p0006"};
        initSampleData.setsPws(sPws);

        String[] sNames = {"agatha","barbara","chris","doris","elva","tiredI"};
        initSampleData.setsNames(sNames);

        int[] sAges = {19,22,20,27,19,23};
        initSampleData.setsAges(sAges);

        char[] sGenders = {'M','W','W','M','M','M'};
        initSampleData.setsGenders(sGenders);

        String[] sMajors = {"English Literature","Korean Language and Literature","French Language and Literature","Philosophy","History","Computer Science"};
        initSampleData.setsMajors(sMajors);

        return initSampleData;
    }

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

    @Bean
    public StudentRegisterService studentRegisterService() {
        return new StudentRegisterService(studentDao());
    }
    @Bean
    public StudentModifyService studentModifyService() {
        return new StudentModifyService(studentDao());
    }
    @Bean
    public StudentDeleteService studentDeleteService() {
        return new StudentDeleteService(studentDao());
    }
    @Bean
    public StudentSelectService studentSelectService() {
        return new StudentSelectService(studentDao());
    }
    @Bean
    public StudentAllSelectService studentAllSelectService() {
        return new StudentAllSelectService(studentDao());
    }
    @Bean
    public PrintStudentInformationService printStudentInformationService() {
        return new PrintStudentInformationService(studentAllSelectService());
    }

    @Bean
    public DBConnectionInfo dev_DBConnectionInfoDev() {
        DBConnectionInfo dbConnectionInfo = new DBConnectionInfo();
        dbConnectionInfo.setUserId("000.000.000.000");
        dbConnectionInfo.setUserId("admin");
        dbConnectionInfo.setUserPw("0000");
        return dbConnectionInfo;
    }
    @Bean
    public DBConnectionInfo real_DBConnectionInfoDev() {
        DBConnectionInfo dbConnectionInfo = new DBConnectionInfo();
        dbConnectionInfo.setUserId("111.111.111.111");
        dbConnectionInfo.setUserId("master");
        dbConnectionInfo.setUserPw("1111");
        return dbConnectionInfo;
    }

    @Bean
    public EMSInformationService eMSInformationService() {
        EMSInformationService emsInformationService = new EMSInformationService();
        emsInformationService.setInfo("Education Management System program was developed in 2022.");
        emsInformationService.setCopyRight("COPYRIGHT(C) 2022 EMS CO., LTD. ALL RIGHT RESERVED. CONTACT MASTER FOR MORE INFORMATION.");
        emsInformationService.setVer("The version is 1.0");
        emsInformationService.setsYear(2022);
        emsInformationService.setsMonth(3);
        emsInformationService.setsDay(1);
        emsInformationService.seteYear(2022);
        emsInformationService.seteMonth(4);
        emsInformationService.seteDay(30);

        List<String> developers = new ArrayList<String>();
        developers.add("Cheney.");
        developers.add("Eloy.");
        developers.add("Jasper.");
        developers.add("Dillon.");
        developers.add("Kian.");
        emsInformationService.setDevelopers(developers);

        Map<String, String> administrators = new HashMap<String, String>();
        administrators.put("Cheney","cheney@springPjt.org");
        administrators.put("Jasper","jasper@springPjt.org");
        emsInformationService.setAdministrators(administrators);

        Map<String, DBConnectionInfo> dbInfos = new HashMap<String, DBConnectionInfo>();
        dbInfos.put("dev", dev_DBConnectionInfoDev());
        dbInfos.put("real", real_DBConnectionInfoDev());
        emsInformationService.setDbInfos(dbInfos);

        return emsInformationService;
    }
}
  • return new StudentRegisterService(studentDao()); : studentRegisterService bean은 StudentRegisterService 타입이고 studentDao bean을 주입받음.
  • dbConnectionInfo.setUserId("000.000.000.000"); : xml의 <property>는 내부적으로 setter 메서드를 호출했다. 이를 java로 옮기려면 setter 메서드를 직접 호출하면 된다.

 


 

나. MainClass 수정

 

//GenericXmlApplicationContext ctx = new GenericXmlApplicationContext("classpath:appCtxImport.xml");
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(MemberConfig.class);

GenericXmlApplicationContext 대신에 AnnotationConfigApplicationContext을 사용함.

AnnotationConfigApplicationContext는 classpath가 아닌 클래스 리터럴(.class)을 필요로 함.

 


 

2. MemberConfig 분리

 

기능 단위로 3개로 분리한다.

  • MemberConfig1 : 학생 정보를 추가, 삭제, 수정, 검색하는 bean 객체를 생성
  • MemberConfig2 : 데이터베이스와 관련한 bean 객체를 생성
  • MemberConfig3 : 시스템 정보와 관련한 bean 객체를 생성
//MemberConfig1
package ch06_pjt_2.ems.configuration;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import ch06_pjt_01.ems.member.dao.StudentDao;
import ch06_pjt_01.ems.member.service.PrintStudentInformationService;
import ch06_pjt_01.ems.member.service.StudentAllSelectService;
import ch06_pjt_01.ems.member.service.StudentDeleteService;
import ch06_pjt_01.ems.member.service.StudentModifyService;
import ch06_pjt_01.ems.member.service.StudentRegisterService;
import ch06_pjt_01.ems.member.service.StudentSelectService;
import ch06_pjt_01.ems.utils.InitSampleData;

@Configuration
public class MemberConfig1 {

    @Bean
    public InitSampleData initSampleData() {
        InitSampleData initSampleData = new InitSampleData();

        String[] sNums = {"hbs001","hbs002","hbs003","hbs004","hbs005","hbs006"};
        initSampleData.setsNums(sNums);

        String[] sIds = {"rabbit","hippo","raccoon","elephant","lion","human"};
        initSampleData.setsIds(sIds);

        String[] sPws = {"p0001","p0002","p0003","p0004","p0005","p0006"};
        initSampleData.setsPws(sPws);

        String[] sNames = {"agatha","barbara","chris","doris","elva","tiredI"};
        initSampleData.setsNames(sNames);

        int[] sAges = {19,22,20,27,19,23};
        initSampleData.setsAges(sAges);

        char[] sGenders = {'M','W','W','M','M','M'};
        initSampleData.setsGenders(sGenders);

        String[] sMajors = {"English Literature","Korean Language and Literature","French Language and Literature","Philosophy","History","Computer Science"};
        initSampleData.setsMajors(sMajors);

        return initSampleData;
    }

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

    @Bean
    public StudentRegisterService studentRegisterService() {
        return new StudentRegisterService(studentDao());
    }
    @Bean
    public StudentModifyService studentModifyService() {
        return new StudentModifyService(studentDao());
    }
    @Bean
    public StudentDeleteService studentDeleteService() {
        return new StudentDeleteService(studentDao());
    }
    @Bean
    public StudentSelectService studentSelectService() {
        return new StudentSelectService(studentDao());
    }
    @Bean
    public StudentAllSelectService studentAllSelectService() {
        return new StudentAllSelectService(studentDao());
    }
    @Bean
    public PrintStudentInformationService printStudentInformationService() {
        return new PrintStudentInformationService(studentAllSelectService());
    }
}
//MemberConfig2 
package ch06_pjt_2.ems.configuration;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import ch06_pjt_01.ems.member.DBConnectionInfo;

@Configuration
public class MemberConfig2 {

    @Bean
    public DBConnectionInfo dev_DBConnectionInfoDev() {
        DBConnectionInfo dbConnectionInfo = new DBConnectionInfo();
        dbConnectionInfo.setUserId("000.000.000.000");
        dbConnectionInfo.setUserId("admin");
        dbConnectionInfo.setUserPw("0000");
        return dbConnectionInfo;
    }
    @Bean
    public DBConnectionInfo real_DBConnectionInfoDev() {
        DBConnectionInfo dbConnectionInfo = new DBConnectionInfo();
        dbConnectionInfo.setUserId("111.111.111.111");
        dbConnectionInfo.setUserId("master");
        dbConnectionInfo.setUserPw("1111");
        return dbConnectionInfo;
    }
}
//MemberConfig3 
package ch06_pjt_2.ems.configuration;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import ch06_pjt_01.ems.member.DBConnectionInfo;
import ch06_pjt_01.ems.member.service.EMSInformationService;

@Configuration
public class MemberConfig3 {

    @Bean
    public EMSInformationService eMSInformationService() {
        EMSInformationService emsInformationService = new EMSInformationService();
        emsInformationService.setInfo("Education Management System program was developed in 2022.");
        emsInformationService.setCopyRight("COPYRIGHT(C) 2022 EMS CO., LTD. ALL RIGHT RESERVED. CONTACT MASTER FOR MORE INFORMATION.");
        emsInformationService.setVer("The version is 1.0");
        emsInformationService.setsYear(2022);
        emsInformationService.setsMonth(3);
        emsInformationService.setsDay(1);
        emsInformationService.seteYear(2022);
        emsInformationService.seteMonth(4);
        emsInformationService.seteDay(30);

        List<String> developers = new ArrayList<String>();
        developers.add("Cheney.");
        developers.add("Eloy.");
        developers.add("Jasper.");
        developers.add("Dillon.");
        developers.add("Kian.");
        emsInformationService.setDevelopers(developers);

        Map<String, String> administrators = new HashMap<String, String>();
        administrators.put("Cheney","cheney@springPjt.org");
        administrators.put("Jasper","jasper@springPjt.org");
        emsInformationService.setAdministrators(administrators);

        Map<String, DBConnectionInfo> dbInfos = new HashMap<String, DBConnectionInfo>();
        dbInfos.put("dev", dev_DBConnectionInfoDev());
        dbInfos.put("real", real_DBConnectionInfoDev());
        emsInformationService.setDbInfos(dbInfos);

        return emsInformationService;
    }
}

파일을 나누고 AnnotationConfigApplicationContext도 수정한다.

 

//MainClass.java
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(MemberConfig1.class, MemeberConfig2.class, MemeberConfig3.class);

 

이때 MemberConfig3에서 문제가 발생한다.

 

이는 분리하면서 MemberConfig3에서 dev_DBConnectionInfoDev()real_DBConnectionInfoDev()를 찾을 수 없기 때문이다.

 


 

나. @Autowired에 의한 의존 객체를 자동 주입.

 

dev_DBConnectionInfoDev()real_DBConnectionInfoDev()@Autowired로 주입받는다.

//Before
dbInfos.put("dev", dev_DBConnectionInfoDev());
dbInfos.put("real", real_DBConnectionInfoDev());

//after
@Autowired
DBConnectionInfo dev_DBConnectionInfoDev;
@Autowired
DBConnectionInfo real_DBConnectionInfoDev;

...

dbInfos.put("dev", dev_DBConnectionInfoDev);
dbInfos.put("real", real_DBConnectionInfoDev);
  • dev_DBConnectionInfoDev()dev_DBConnectionInfoDev 바뀜.

 

//MemberConfig3 
package ch06_pjt_2.ems.configuration;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import ch06_pjt_01.ems.member.DBConnectionInfo;
import ch06_pjt_01.ems.member.service.EMSInformationService;

@Configuration
public class MemberConfig3 {

    @Autowired
    DBConnectionInfo dev_DBConnectionInfoDev; //이부분

    @Autowired
    DBConnectionInfo real_DBConnectionInfoDev; // 이부분

    @Bean
    public EMSInformationService eMSInformationService() {
        EMSInformationService emsInformationService = new EMSInformationService();
        emsInformationService.setInfo("Education Management System program was developed in 2022.");
        emsInformationService.setCopyRight("COPYRIGHT(C) 2022 EMS CO., LTD. ALL RIGHT RESERVED. CONTACT MASTER FOR MORE INFORMATION.");
        emsInformationService.setVer("The version is 1.0");
        emsInformationService.setsYear(2022);
        emsInformationService.setsMonth(3);
        emsInformationService.setsDay(1);
        emsInformationService.seteYear(2022);
        emsInformationService.seteMonth(4);
        emsInformationService.seteDay(30);

        List<String> developers = new ArrayList<String>();
        developers.add("Cheney.");
        developers.add("Eloy.");
        developers.add("Jasper.");
        developers.add("Dillon.");
        developers.add("Kian.");
        emsInformationService.setDevelopers(developers);

        Map<String, String> administrators = new HashMap<String, String>();
        administrators.put("Cheney","cheney@springPjt.org");
        administrators.put("Jasper","jasper@springPjt.org");
        emsInformationService.setAdministrators(administrators);

        Map<String, DBConnectionInfo> dbInfos = new HashMap<String, DBConnectionInfo>();
        dbInfos.put("dev", dev_DBConnectionInfoDev);
        dbInfos.put("real", real_DBConnectionInfoDev);
        emsInformationService.setDbInfos(dbInfos);

        return emsInformationService;
    }
}

 


 

다. @Import annotation

 

MemberConfig1, MemberConfig2, MemberConfig3을 묶는다.

 

MemberConfig1 복사해서 MemberConfigImport 생성.

 

//MemberConfigImport
@Configuration
@Import({MemberConfig2.class, MemberConfig3.class})
public class MemberConfigImport {
    ...
}
  • @Import({MemberConfig2.class, MemberConfig3.class}) : MemberConfigImportMemberConfig2MemberConfig3을 import 한다.

 

//MainClass

// before
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(MemberConfig1.class, MemeberConfig2.class, MemeberConfig3.class);

//after
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(MemberConfigImport.class);

 

이전에 비해 간단해졌다.