반응형
2021-05-28글
스프링은 객체 컨테이너
BeanFactory
- 객체 생성과 검색에 대한 기능 정의
getBean()
: 생성된 객체를 검색하는데 필요한 메서드- 객체 검색 이외에도 싱글톤인지 프로토타입 빈인지 확인하는 기능도 있음
AnnotationContext
- 메시지, profile, 환경 변수 등을 처리할 수 있는 기능을 추가로 쩡의
의존이란?
DI를 통한 의존 처리
의존이란?
한 클래스가 다른 클래스의 메서드를 실행할 때 의존한다고 표현
변경에 의해 영향을 받는 관계를 의미
DI는 의존하는 객체를 직접 생성하지 않고, 의존 객체를 주입받는 방식을 사용
DI를 통해 객체를 주입하면 유지보수성이 더 올라간다.
스프링의 DI 설정
- 스프링은 DI를 이용해서 객체를 서로 연결해주는 조립기이다.
- 특정 타입의 클래스만 생성하는 조립기가 아닌 범용 조립기이다.
설정 클래스
@Configuration
public class AppCtx {
@Bean
public MemberDao memberDao() {
return new MemberDao();
}
@Bean
public MemberRegisterService memberRegSvc() {
return new MemberRegisterService(memberDao()); // memberDao() 가 생성한 객체를 주입
}
@Bean
public ChangePasswordService changePwSvc() {
ChangePasswordService pwsSvc = new ChangePasswordService();
pwdSvc.setMemberDao(memberDao());
return pwdSvc;
}
}
@Configuration
: 스프링 설정 클래스@Bean
: 해당 메서드가 생성한 객체를 스프링 빈으로 설정- 메서드 이름을 빈 객체의 이름으로 사용
설정 클래스만 만들어서 끝나는 것이 아닌, 설정 클래스로 컨테이너를 생성해야 한다.
ApplicationContext ctx = new AnnotationConfigApplicationContext(AppCtx.class)
// ...
MemberRegisterService regSvc = ctx.getBean("memberRegSvc", MemberRegisterService.class)
- 컨테이너를 생성하면
getBean()
를 이용해 사용할 객체를 구할 수 있음 - 스프링 컨테이너
ctx
로터 이름이 "memberRegSvc"인 빈 객체를 구함
DI 방식 - 생성자 방식
public class StationService {
private StationDao stationDao;
public StationService(StationDao stationDao) {
this.stationDao = stationDao;
}
}
DI 방식 - 생성자 방식
public class StationService {
private StationDao stationDao;
public void setStationDao(StationDao stationDao) {
this.stationDao = stationDao;
}
}
@Configuration 설정 클래스의 @Bean 설정과 싱글톤
@Configuration
public class AppCtx {
@Bean
public MemberDao memberDao() {
return new MemberDao();
}
@Bean
public MemberRegisterService memberRegSvc() {
return new MemberRegisterService(memberDao()); // memberDao() 가 생성한 객체를 주입
}
@Bean
public ChangePasswordService changePwSvc() {
ChangePasswordService pwsSvc = new ChangePasswordService();
pwdSvc.setMemberDao(memberDao());
return pwdSvc;
}
}
memberDao()
는 매번 새로운 MemberDao 객체를 생성해서 반환한다.
그러면 memberRegSvc()
가 반환하는 객체와 changePwSvc()
가 반환하는 객체는 서로 다른 MemberDao 객체를 사용하는 것인가?
🙅♀️ 스프링 컨테이너가 생성한 빈은 싱글톤 객체이다.@Bean
이 붙은 메서드에 대해 한 개의 객체만 생성하고 이를 보관했다가, 동일한 객체를 반환한다.
두 개 이상의 설정 파일 사용하기
스프링은 한 개 이상의 설정 파일을 이용해서 컨테이너를 생성할 수 있다.
@Configuration, @Autowired
AppConf1
@Configuration
public class AppConf1 {
@Bean
public MemberDao memberDao() {
return new MemberDao();
}
@Bean
public MemberPrinter memberPrinter() {
return new MemberPrinter();
}
}
AppConf2
@Configuration
public class AppConf2 {
@Autowired
private MemberDao memberDao;
@Autowired
private MemberPrinter memberPrinter;
@Bean
public MemberRegisterService memberRegSvc() {
return new MemberRegisterService(memberDao);
}
@Bean
public ChangePasswordService changePwdSvc() {
ChangePasswordService pwdSvc = new ChangePasswordService();
pwdSvc.setMemberDao(memberDao);
return pwdSvc;
}
@Bean
public MemberListPrinter listPrinter() {
return new MemberListPrinter(memberDao, memberPrinter);
}
@Bean
public MemberInfoPrinter infoPrinter() {
MemberInfoPrinter infoPrinter = new MemberInfoPrinter();
infoPrinter.setMemberDao(memberDao);
infoPrinter.setPrinter(memberPrinter);
return infoPrinter;
}
@Bean
public VersionPrinter versionPrinter() {
VersionPrinter versionPrinter = new VersionPrinter();
versionPrinter.setMajorVersion(5);
versionPrinter.setMinorVersion(0);
return versionPrinter;
}
}
@AutoWired
: 스프링의 자동 주입 기능. 스프링 설정 클래스 필드에 해당 어노테이션을 붙이면 해당 타입 빈을 찾아서 필드에 할당한다.- AppConf2의 memberDao 필드에는 AppConf1 클래스에서 설정한 빈이 할당된다.
- 스프링 컨테이너는 AppConf2 객체를 빈으로 등록하고
@AutoWired
가 붙은 대상에 대해 알맞은 빈을 자동으로 주입한다.
설정 클래스가 여러개일 때 스프링 컨테이너를 생성하는 방법은?
ctx = new AnnotationConfigApplicationContext(AppConf1.class, AppConf2.class)
- AnnotationConfigApplicationContext의 생성자의 인자는 가변 인자이다.
@Import 어노테이션 사용
- 함께 사용할 설정 클래스를 지정
@Configuration
@Import({AppConf2.class})
public class AppConfImport {
@Bean
public MemberDao memberDao() {
return new MemberDao();
}
@Bean
public MemberPrinter memberPrinter() {
return new MemberPrinter();
}
}
- 지정한 클래스도 함께 사용하기 때문에 스프링 컨테이너를 생성할 때 AppConfi2를 지정할 필요가 없다.
getBean()
VersionPrinter versionPrinter = ctx.getBean("versionPrinter", VersionPrinter.class)
- 첫번째 인자는 빈의 이름
- 두번째 인자는 빈의 타입
- 빈의 이름을 지정하지 않고 타입만으로 빈을 구할 수도 있다.
- 대신 해당 타입의 빈 객체가 한 개만 존재해야한다.
주입 대상 객체를 모두 빈 객체로 설정해야하나?
🙅♀️ 스프링 컨테이너가 객체를 관리하는지 여부만 다를 뿐이다.
참고로 스프링 컨테이너는 자동 주입, 라이프사이클 관리 등 객체 생성 외에도 객체 관리를 위한 다양한 기능을 제공한다.
반응형
'스프링 부트' 카테고리의 다른 글
스프링 부트 Profile별로 다른 환경 구성 (0) | 2021.08.06 |
---|---|
📋 4. 의존 자동 주입 (0) | 2021.08.06 |
SpringBoot Auto Configuration (0) | 2021.08.06 |
📋 Spring MVC - 5. 스프링 MVC (0) | 2021.08.06 |
📋 Spring MVC - 4. MVC 프레임워크 만들기 (0) | 2021.08.06 |