우선 빈 객체를 등록할때 설정클래스에서(@Configuration) 어떤 빈 객체의 의존 주입하는 방식은 2가지가 있다.
1.첫번째는, 앞 포스트에서 설명했던 것 처럼 생성자의 파라미터로 의존의 대상이되는 객체를 넣어주는 것이다.[ 실제@Configuration 클래스에서는 객체설정메서드(@Bean) 를 파라미터로 넘겨줌]
장점: 빈 객체를 설정할때 이미 그 클래스가 의존하는 모든 객체를 주입받기 때문에, 완벽한 상태(그 클래스가 의존하는 모든 클래스의 메서드 들을 사용가능) 에서 빈 객체를 사용 가능하다.
단점: 생성자의 파라미터 개수가 많을 경우, 어떤 객체가 들어가야할지 모를 수 있어서 생성자 코드를 직접 확인해 봐야한다....라고 책에서 주장하는데 나는 그렇게 생각하지 않는다.IntelliJ는 애초에 입력하는 과정에서 다 알려주지 않나..?? 아무래도 3년 전에 쓰여진 책이라서 이런걸 단점이라고 생각하는거 같다.
2. 두번째는 설정 메서드 Setter를 이용하는 방식이다. 그 클래스의 인스턴스변수가 Private일때 set 함수를 사용자가 만들어서 인스턴스 변수를 초기화 해주는 방법은 이미 내가 자바 공부하면서 많이 써봐서, 특별히 다른점은 없다.
장점:
자바빈 규칙
-메서드 이름이 set으로 시작한다.
-set뒤에 첫 글자는 대문자로 시작한다.
-파라미터가 1개이다.
-리턴타입이 void 이다.
자바빈 규칙에 의거해서 setter을 만들어 주기 때문에, 이름을 통해 어떤 객체가 주입되는지 쉽게 유추할 수 있다.
단점: 생성자를 이용한 주입처럼 한번에 모든 객체가 다 주입되는것이 아니고, 세터 방식은 세터 메서드를 사용해서 필요한 의존객체를 전달하지 않아도 빈 객체가 생성되기 때문에 객체를 사용하는 시점에 NullPointerException이 발생할 수 있다.
아래의 코드는 빈 설정클래스@Configuration에서 생성자 방식과 설정메서드 방식을 보여준다. 비교해 보자.
@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);//바로 앞 포스트에서 설명한, 생성자의
//파라미터가 2개일때 의존주입하는 것.
}
@Bean
public MemberInfoPrinter infoPrinter() {
MemberInfoPrinter infoPrinter = new MemberInfoPrinter();
infoPrinter.setMemberDao(memberDao);//설정 메서드 세터를 사용한 DI. 이 메서드가 없어도 빈객체 설정됨.
infoPrinter.setPrinter(memberPrinter);
return infoPrinter;
}
@Bean
public VersionPrinter versionPrinter() {
VersionPrinter versionPrinter = new VersionPrinter();
versionPrinter.setMajorVersion(5);
versionPrinter.setMinorVersion(0);
return versionPrinter;
}
}
여기서 궁금증이 일어날 수 있다. 바로 @Bean메서드에 생성자 방식이던, 세터방식이던 설정메서드를 호출함으로써, 의존주입 하는 것을 볼 수 있다. 예) memberDao()메서드는 거의 모든 클래스의 생성자에 호출된다.(의존주입된다.)
그렇다면, 각각 memberDao() 는 클래스마다 서로다른 객체를 새로 생성해서 의존주입되는 것일까? 그러니깐 내 궁금증을 이해하기 쉽게 풀어쓰자면, memberRegSvc()빈 객체 가 의존하는 memberDao()와 changePwdSvc() 빈객체가 의존하는 memberDao()는 다른 것이냔 말이다.
결론은 아니다. 왜냐하면, 스프링 컨테이너에 @Configuration(설정클래스)을 통해 빈객체를 등록할때,
[AnnotationConfigApplicationContext
컨테이너에서 알아서 각 @Bean 메서드에 구현된 객체들을 오로지 1개만 생성해서 빈객체로 등록시킨다.
왜냐하면, 스프링은 설정클래스를 그대로 사용하지 않고, 설정 클래스를 새로 만들어서 사용하기 때문이다.
또 알게된 단편적 지식들
1. 스프링 컨테이너에 등록할때, 여러개의 설정클래스로 등록 가능하다.
AbstractApplicationContext ctx=
new AnnotationConfigApplicationContext(AppConf1.class,AppConfig2.class)
2.@Autowired 이 붙은 참조변수는 스프링이 자동으로 스프링 빈에 등록된 객체들 중 해당 타입의 빈을 찾아서 필드에 할당한다. 즉, 따로 @Configuration 클래스 설정정보에서 새로운 @Bean을 일일이 등록 할 필요 없다는 이야기이다.
즉 ,위 예시로 예로 들자면, 만약 AppConf1 설정클래스에 memberDao가 등록되 있으면, AppConfig2 설정클래스에서 빈 객체를 등록할때 memberDao 객체를 의존주입 해야 한다면, AppConfig2 설정 클래스에서 다시 @Bean 이렇게 memberDao를 설정하는 것이 아니라, @AutoWired 애너테이션을 사용하면, 이미 AppConf1에 memberDao 빈 객체가 등록되어 있으므로 스프링이 알아서 찾아서 AppConfg2에 주입해준다.
3. @Import 애너테이션을 다른 설정 클래스를 사용하면 아예 함께 사용할 설정 클래스를 지정해서, 한개의 클래스만 컨테이너에 등록해도, 여러개의 설정 클래스를 등록한 효과를 보여준다.
page 102 공부완료.
순공부 /실습시간 2시간.
'기록 > Spring framework' 카테고리의 다른 글
자동의존의 대상이 되는 클래스가 자손클래스일때, @Autowired 사용시 에러 처리법. 2021-06-01 (0) | 2021.06.01 |
---|---|
스프링 의존 자동 주입 @Autowired와 @Qualifier, 2021-05-31 (0) | 2021.06.01 |
스프링의 근원적 역할= 객체조립기, [최범균 스프링5 책] 2021-05-28 (0) | 2021.05.27 |
스프링 객체조립기(assembler), 백준 11725번 문제를 풀며 든 인접리스트에 대한 생각. [최범균 스프링 5] 2021-05-26 (0) | 2021.05.27 |
스프링 DI 공부 및 내가 실수했던 것들[최범균의 스프링5 책](2021-05-26) (0) | 2021.05.26 |