참고도서
|
1. @Configuration / @Bean
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 | package spring; // @Configuration -> 스프링 설정으로 사용되는 클래스라는 것을 알림 @Configuration public class JavaConfig{ // @Bean -> 스프링 컨테이너가 생성할 빈 객체라는 것을 알림 // [@Bean] -> <bean [memberDao, 메소드명] -> id="memberDao" // [MemberDao, 메소드 반환 객체] -> class="spring.MemberDao" /> // spring.MemberDao 클래스로부터 memberDao라는 이름의 인스턴스 객체를 생성 @Bean public MemberDao memberDao(){ return new MemberDao(); } @Bean public MemberRegisterService memberRegSvc(){ // memberDao() 메소드를 호출하고, 메소드로부터 의존 객체를 리턴받아 주입함 // [MemberRegisterService(memberDao()), 생성자] -> <constructor-arg // [memberDao(), 메소드명] -> ref="memberDao" /> // MemberRegisterService 클래스에는 MemberDao 객체를 매개변수로 받는 생성자가 있어야 한다. // private MemberDao memberDao; // public MemberRegisterService(MemberDao memberDao){this.memberDao=memberDao;} return new MemberRegisterService(memberDao()); } @Bean public MemberPrinter printer(){ return new MemberPrinter(); } @Bean public MemberInfoPrinter infoPrinter(){ MemberInfoPrinter infoPrinter = new MemberInfoPrinter(); // [infoPrinter.setMemberDao(memberDao());] setter -> <property // [setMemberDao, setter 메소드명] -> name="memberDao" // [memberDao(), 주입할 객체를 생성하는 메소드명] -> ref="memberDao" /> infoPrinter.setMemberDao(memberDao()); infoPrinter.setPrinter(printer()); return infoPrinter; } } |
(2) 자바 설정 파일을 가지고 스프링 컨테이너 생성
1 2 3 4 5 6 7 8 9 10 11 12 13 | public class Main{ public static void main(String[] args){ // XML 기반 설정 -> GenericXmlApplicationContext 클래스 사용 // 자바 기반 설정 -> AnnotationConfigApplicationContext 사용 // JavaConfig.class -> JavaConfig 클래스를 설정 파일로 사용 ApplicationContext ctx = new AnnotationConfigApplicationContext(JavaConfig.class); // "memberRegSvc" -> 자바 설정 파일의 메소드명 // MemberRegisterService.class -> 빈 객체를 생성할 때 사용할 MemberRegisterService regSvc = ctx.getBean("memberRegSvc", MemberRegisterService.class); } } | cs |
(3) 자바 기반 설정의 동작 방식
생성자 MemberRegisterService(memberDao( )); 에서 호출하는 memberDao( ) 메소드가 반환하는 MemberDao 객체와
setter 메소드 infoPrinter.setMemberDao(memberDao( )); 에서 호출하는 memberDao( ) 메소드가 반환하는 MemberDao 객체는
같은 객체이다.
자바 기반 설정에서도 XML 설정과 마찬가지로 빈 객체는 기본적으로 싱글톤 범위를 가진다.
싱글톤 범위의 빈 객체를 만들기 위해 스프링은 설정 클래스를 상속받는 클래스를 만들고 새로운 객체를 생성한다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | // 자바 기반 설정 클래스를 상속받아 스프링이 만드는 클래스 public class SpringExtConfig extends JavaConfig{ private MemberDao memberDaoBean; @Bean public MemberDao memberDao(){ // memberDaoBean 이 null -> 처음 생성될 때 // super.memberDao(); -> 상속하고 있는 자바 기반 설정 클래스로부터 // MemberDao 객체를 생성해서 memberDaoBean 필드에 담는다 if(memberDaoBean == null){ memberDaoBean = super.memberDao(); } // memberDaoBean 필드에 MemberDao 객체가 담겨 있으면 // 새로운 MemberDao 객체를 만들지 않고 기존에 생성되어 있는 객체를 반환 // 즉 늘 같은 MemeberDao 객체가 반환됨 -> return memberDaoBean; } } | cs |
스프링은 @Configuration 설정 클래스를 상속받아 새로운 클래스를 만들기 위해 CGLIB 이라는 기술을 사용하는데,
CGLIB 가 클래스를 상속받아 새로운 클래스를 생성할 수 있으려면 두 가지 조건을 충족해야 한다.
① 클래스가 final 이어사는 안 된다.
② 파라미터(매개변수)가 없는 기본 생성자를 제공해야 한다.
그러므로 @Configuration 어노테이션을 적용한 자바 설정 클래스도 두 조건을 충족해야 한다.
3. 자바 기반 설정에서의 자동 주입
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 | public class MemberInfoPrinter{ private MemberDao memDao; private MemberPrinter printer; // MemberDao 타입의 빈 객체를 찾아서 setMemberDao() 메소드의 매개변수에 자동 주입 @Autowired public void setMemberDao(MemberDao memberDao){ this.memDao = memberDao; } @Autowired public void setPrinter(MemberPrinter printer){ this.printer = printer; } } public class JavaConfig{ @Bean public MemberDao memberDao(){ return new MemberDao(); } @Bean public MemberPrinter printer(){ return new MemberPrinter(); } @Bean public MemberInfoPrinter infoPrinter(){ // MemberInfoPrinter 객체가 생성될 때, // MemberInfoPrinter 클래스의 @Autowired 가 붙은 곳에서 자동 주입이 일어난다 // 자동 주입에 의해 MemberInfoPrinter 객체는 MemberDao, MemberPrinter 객체를 필드로 가지고 생성된다. // 자동 주입이 발생하기 때문에, // infoPrinter.setMemberDao(memberDao()), infoPrinter.setPrinter(printer()) 설정은 필요 없다. MemberInfoPrinter infoPrinter = new MemberInfoPrinter(); return infoPrinter; } } | cs |
주의해야할 점은 XML 기반 설정에서 @Autowired 어노테이션은 생성자, 필드, 메소드에서 사용 가능했다.
그러나 자바 기반 설정에서는 @Autowired 어노테이션이 붙은 필드, 메소드에는 자동 주입이 발생하지만
생성자에는 @Autowired 어노테이션을 붙여도 자동주입이 발생하지 않는다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | @Bean public MemberRegisterService memberRegSvc(){ // 자바 기반 설정 클래스에서 생성자를 이용해서 객체를 생성 // 여기서 MemberDao 객체를 주입해야 하기 때문에 // MemberRegisterService 클래스의 생성자에서 자동 주입을 설정해도 // 자동 주입된 MemberRegisterService 객체를 얻을 수 없다. // 즉, MemberRegisterService 클래스의 생성자에 @Autowired 어노테이션을 붙이고 // return new MemberRegisterService(); 처럼 사용할 수 없다. return new MemberRegisterService(memberDao()); } // XML 설정과 달리 자바 설정을 사용할 때는 스프링 컨테이너가 객체를 생성할 때 // 사용할 생성자를 결정할 수 없고, 따라서 생성자를 통한 의존 객체 자동 주입을 // 적용할 수 없는 것이다. // XML 설정은 객체를 생성할 때 해당 클래스를 찾아가기 때문에 생성자를 통한 // 자동 주입이 가능하다. | cs |
자동 주입은 @Autowired 어노테이션을 쓰지 않고
@Configuration 클래스의 @Bean 메소드 파라미터를 통해서도 주입할 수 있다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | @Configuration public class JavaConfig{ @Bean public MemberDao memberDao(){ return new MemberDao(); } @Bean public MemberPrinter printer(){ return new MemberPrinter(); } // 스프링 컨테이너느 infoPrinter 메소드에 설정되어 있는 // MemberDao, MemberPrinter 타입 객체를 찾아서 자동 주입한다. @Bean public MemberInfoPrinter infoPrinter(MemberDao memDao, MemberPrinter memPrt){ MemberInfoPrinter infoPrinter = new MemberInfoPrinter(); infoPrinter.setMemberDao(memDao); infoPrinter.setPrinter(memPrt); return infoPrinter; } } | cs |
4. 두 개 이상의 클래스를 사용한 설정
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 | @Configuration public class ConfigPart1{ @Bean public MemberDao memberDao(){ return new MemberDao(); } @Bean public MemberRegisterService memberRegSvc(){ return new MemberRegisterService(memberDao()); } } @Configuration public class ConfigPart2{ // @Configuration 이 붙은 클래스에도 자동 주입을 사용할 수 있다. // ConfigPart2 클래스의 infoPrinter 메소드에 MemberDao 객체가 필요하지만 // ConfigPart2 클래스에는 MemberDao 객체를 생성하는 코드가 없고, ConfigPart1 에 있다. // ConfigPart1 클래스에서 생성된 MemberDao 객체를 자동 주입해서 받아서 // ConfigPart2 클래스의 infoPrinter 메소드에서 사용하고 있다. @Autoriwed private MemberDao memberDao; @Bean public MemberPrinter printer(){ return new MemberPrinter(); } @Bean public MemberInfoPrinter infoPrinter(){ MemberInfoPrinter infoPrinter = new MemberInfoPrinter(); infoPrinter.setMemberDao(memberDao); infoPrinter.setPrinter(printer()); return infoPrinter; } } | cs |
(2) @Configuration 클래스 주입 받아 의존 설정
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 | @Configuration public class ConfigPart1{ @Bean public MemberDao memberDao(){ return new MemberDao(); } @Bean public MemberRegisterService memberRegSvc(){ return new MemberRegisterService(memberDao()); } } @Configuration public class ConfigPart2{ // 또 다른 스프링 설정 파일인 ConfigPart1 객체를 통째로 자동 주입 받을 수 있다. @Autoriwed private ConfigPart1 configPart1; @Bean public MemberPrinter printer(){ return new MemberPrinter(); } @Bean public MemberInfoPrinter infoPrinter(){ MemberInfoPrinter infoPrinter = new MemberInfoPrinter(); // 자동 주입된 ConfigPart1 객체를 통해서, ConfigPart1에 생성된 memberDao 객체를 가져온다 infoPrinter.setMemberDao(configPart1.memberDao); infoPrinter.setPrinter(printer()); return infoPrinter; } } // 두 개 이상인 자바 기반 설정 파일 사용하기 public class MainTwoConfs{ public static void main(String[] args){ ApplicationContext ctx = new AnnotationConfigApplicationContext(ConfigPart1.class, ConfigPart2.class); } } | cs |
(3) @Import 어노테이션 사용
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 | @Configuration public class ConfigPartSub{ @Autoriwed private MemberDao memberDao; @Bean public MemberPrinter printer(){ return new MemberPrinter(); } @Bean public MemberInfoPrinter infoPrinter(){ MemberInfoPrinter infoPrinter = new MemberInfoPrinter(); infoPrinter.setMemberDao(memberDao); infoPrinter.setPrinter(printer()); return infoPrinter; } } // @Import 어노테이션을 사용해서 또 다른 설정 파일인 ConfigPartSub 클래스도 // 자바 기반 설정 파일로 사용하겠다고 알린다 // @Import(ConfigPartSub1.class, ConfigPartSub2.class) 처럼 여러 개 지정 가능 @Configuration @Import(ConfigPartSub.class) public class ConfigPartMain{ @Bean public MemberDao memberDao(){ return new MemberDao(); } @Bean public MemberRegisterService memberRegSvc(){ return new MemberRegisterService(memberDao()); } } // 두 개 이상인 자바 기반 설정 파일 사용하기 public class MainTwoConfs{ public static void main(String[] args){ // ConfigPartMain.class 만 설정 파일로 지정해도 // @Import(ConfigPartSub.class) 어노테이션에 의해 ConfigPartSub 도 설정 된다. ApplicationContext ctx = new AnnotationConfigApplicationContext(ConfigPartMain.class); } } | cs |
5. 자바 기반 설정과 XML 기반 설정의 혼합
(1) 자바 설정에서 XML 설정 임포트
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 | <!-- XML 기반 설정 파일, sub-conf.xml --> <bean id="memberDao" class="spring.MemberDao"/> <bean id="infoPrinter" class="spring.MemberInfoPrinter"> <property name="memberDao" ref="memberDao"/> <property name="printer" ref="memberPrinter"/> </bean> // 자바 기반 설정 파일 // XML 설정 파일을 임포트 할 때는 @ImportResource 어노테이션을 사용하면 된다 @Configuration @ImportResource("classpath:sub-conf.xml") public class JavaMainConf{ @Autowired private MemberDao memberDao; @Bean public MemberPrinter memberPrinter(){ return new MemberPrinter(); } @Bean public MemberRegisterService memberRegSvc(){ return new MemberRegisterService(memberDao); } } // 설정 파일 사용하기 public class MainTwoConfs{ public static void main(String[] args){ ApplicationContext ctx = new AnnotationConfigApplicationContext(JavaMainConf.class); } } | cs |
(2) XML 설정에서 자바 설정 임포트
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 | <!-- XML 기반 설정 파일, main-conf.xml --> <!-- XML 설정을 메인으로 사용할 때는 자바 설정 파일의 빈을 사용하기 위해 --> <!-- <context:annotation-config/> 을 설정해야 한다. --> <context:annotation-config/> <!-- @Configuration 이 붙은 JavaSubConf 클래스의 객체를 만들기 위해 빈 설정 --> <bean class="config.JavaSubConf"/> <bean id="memberDao" class="spring.MemberDao"/> <bean id="infoPrinter" class="spring.MemberInfoPrinter"> <property name="memberDao" ref="memberDao"/> <property name="printer" ref="memberPrinter"/> </bean> // 자바 기반 설정 파일 @Configuration public class JavaSubConf{ @Autowired private MemberDao memberDao; @Bean public MemberPrinter memberPrinter(){ return new MemberPrinter(); } @Bean public MemberRegisterService memberRegSvc(){ return new MemberRegisterService(memberDao); } } // 설정 파일 사용하기 public class MainTwoConfs{ public static void main(String[] args){ ApplicationContext ctx = new AnnotationConfigApplicationContext("classpath:main-conf.xml"); } } | cs |
'Programming > Spring' 카테고리의 다른 글
AOP 기초 (0) | 2017.08.19 |
---|---|
Bean 라이프 사이클과 범위 (0) | 2017.08.19 |
의존 자동 주입 (0) | 2017.08.18 |
Spring DI (0) | 2017.08.18 |
Maven / Spring 기본 (0) | 2017.08.18 |
댓글