스프링에서 DI 방식은 크게 생성자 주입 방식도 있고, 세터 메서드를 통해서 의존 주입도 가능하다.
@Configuration
public class AppCtx1 {
@Bean
public MemberDao memberdao() {
MemberDao m=new MemberDao();
return m;
}
@Bean
public MemberRegisterService mrsvc() {
MemberRegisterService mrsvc=new MemberRegisterService(memberdao());
//생성자를 통한 DI
return mrsvc;
}
@Bean
public PasswordChangeService pcsvc() {
PasswordChangeService pcsvc=new PasswordChangeService(memberdao());
//생성자를 통한 DI
return pcsvc;
}
}
위에 내가 정의한 설정 클래스의 두 자바빈 객체는 다 생성자 주입 방식을 사용했다.
@Configuration
public class AppCtx2 {
@Autowired private MemberDao memberdao;
@Bean
public MemberPrinter printer() {
MemberPrinter printer=new MemberPrinter();
printer.setMemberDao(memberdao);
//세터 메서드(설정 메서드)를 통한 DI.
return printer;
}
}
위 설정 클래스에서는 세터 메서드를 통하여 MemberPrinter 클래스의 MemberDao 프로퍼티* 를 의존주입 하였다.
** 프로퍼티라고 책에 나와서 뜻을 찾아보았는데 영어로는 '자산' 이라는 뜻이고, 프로그래밍 적으로는 해당 객체의 '속성'(멤버변수) 라고 해석하면 된다.
@Autowired 애너테이션은 해당 클래스타입의 빈을 스프링 컨테이너에서 자동으로 찾아서 주입해준다. 즉, 위 코드를 예시로 들자면, MemberDao 타입의 객체가 스프링 컨테이너에 "빈"으로 등록되어 있어야지 가능하다.
그럼의아할 수 있다. 일반 클래스가 아니라 설정클래스에도 @Autowired를 설정 클래스에도 붙일수 있을까?
내가 왜 이런 궁금증을 가졌냐면, @Autowired는 일반적으로 어떠한 방식으로 쓰이는 방식은 설정 클래스가 아니라 자바빈으로 등록할 클래스를 정의하는 과정에서 쓰인다. 예를들면 기존MemberRegisterService 클래스를 정의할때, MemberDao 클래스의 객체를 설정클래스에서 생성자 방식으로 DI 하는 방식을 썼다.
public class MemberRegisterService {
private MemberDao memberdao;
public MemberRegisterService(MemberDao memberdao) {
this.memberdao = memberdao;
}
public void registermember(Member m) {
Member m1=memberdao.getidentifier(m);
if(m1!=null) {
throw new DuplicateMemberException("등록된 멤버의 ID가 중복되어있습니다.");
}
else {
memberdao.register(m);
System.out.println("등록완료 ID: "+m.getId()+" pwd: "+m.getPwd() );
}
}
}
@Configuration
public class AppCtx1 {
@Bean
public MemberDao memberdao() {
MemberDao m=new MemberDao();
return m;
}
@Bean
public MemberRegisterService mrsvc() {
MemberRegisterService mrsvc=new MemberRegisterService(memberdao());
//생성자로 DI 해야함.
return mrsvc;
}
@Bean
public PasswordChangeService pcsvc() {
PasswordChangeService pcsvc=new PasswordChangeService(memberdao());
return pcsvc;
}
}
스프링 설정 클래스에서 수동으로 memberdao() 메서드를 호출하여서 생성자DI 방식을 썼다.
이렇게 MemberDao 객체를 생성자를 통해서 수동으로 DI 하는 방식에서, @Autowired 애너테이션을 사용하면, 그런 과정이 사라진다. 원리는, 이미 스프링 컨테이너에 등록된 MemberDao 객체를 주입하기 때문이다.
public class MemberRegisterService {
@Autowired private MemberDao memberdao;
/* public MemberRegisterService(MemberDao memberdao) {
this.memberdao = memberdao;
}*/
public MemberRegisterService() {
// TODO Auto-generated constructor stub
}
public void registermember(Member m) {
Member m1=memberdao.getidentifier(m);
if(m1!=null) {
throw new DuplicateMemberException("등록된 멤버의 ID가 중복되어있습니다.");
}
else {
memberdao.register(m);
System.out.println("등록완료 ID: "+m.getId()+" pwd: "+m.getPwd() );
}
}
}
@Configuration
public class AppCtx1 {
@Bean
public MemberDao memberdao() {
MemberDao m=new MemberDao();
return m;
}
@Bean
public MemberRegisterService mrsvc() {
MemberRegisterService mrsvc=new MemberRegisterService();
//생성자 DI 방식을 쓰지 않아도 자동으로 memberdao가 해당 구현 클래스 안에 DI되있음.
//불필요한 수동 DI 방식 안써도 됨.
return mrsvc;
}
@Bean
public PasswordChangeService pcsvc() {
PasswordChangeService pcsvc=new PasswordChangeService(memberdao());
return pcsvc;
}
}
그렇다면 설정 클래스에도 사용 가능할까?
가능하다. 그러나 @Autowired로 붙이는 클래스의 타입이 스프링 컨테이너에 빈으로 등록되어 있어야 한다.
@Configuration
public class AppCtx2 {
@Autowired private MemberDao memberdao;
@Bean
public MemberPrinter printer() {
MemberPrinter printer=new MemberPrinter();
printer.setMemberDao(memberdao);// 별도의 빈 매서드를 호출하지 않아도
//자동주입된 memberdao를 이용.
return printer;
}
}
이렇게 설정 클래스 1개를 더 만든다면, 내가 위에서 이미 완성한 AppCtx1 에서 MemberDao 타입의 빈을 이미 등록 했기 때문에, 세터DI를 할때 그냥 memberdao 파라미터를 넣어주기만 하면 된다.
이렇게 일반클래스에서 @Autowired로 맴버에 객체가 주입된원리와 "똑같이" 설정클래스에서도 가능하다.
이유는 이 @Configuration이라고 붙은 설정 클래스(AppCtx2)를 ApplicationContext 를 통해 컨테이너 생성할때, 설정클래스 (AppCtx2) 의 객체도 @Bean이라 붙인 객체들과 함께, 스프링 빈에 등록이 된다는 것이다. 그래서 일반 클래스 뿐만 아니라 위 사례처럼 @Autowired를 설정클래스에 사용해도 된다.
최종수정 2021-11-09.
울산 남구 청년 일자리 카페에서.
'기록 > Spring framework' 카테고리의 다른 글
의존 자동주입 할때 타입이 일치하는 빈 중 의존 주입할 대상 빈을 선택하는 방법: @Qualifer 이용법. 2021-11-12 (0) | 2021.11.12 |
---|---|
자동 의존 주입 @Autowired 의 실질적 적용 (세터 메서드, 필드). 2021-11-11 (0) | 2021.11.11 |
스프링의 역할: 객체 조립기(@Configuration) (0) | 2021.10.19 |
객체 조립기(Assembler)의 필요성. 2021-10-18 (0) | 2021.10.15 |
메이븐프로젝트의 식별자: 아티팩트ID 2021-10-13. (0) | 2021.10.13 |