dev/Spring

[Spring] DI 예제1

dev_Step 2022. 1. 11. 23:38

@Data // lombok의 setter를 생성하는 기능과, 생성자, toString() 등을 자동으로 생성하도록 하는 어노테이션.

@Component는 스프링에게 해당 클래스가 스프링에서 관리해야 하는 대상임을 표시하는 어노테이션이며,

@Setter는 자동으로 setChef() 를 컴파일시 생성합니다.

Setter에서 사용된 onMethod 속성은 생성되는 setChef()에 @Autowired 어노테이션을 추가하도록 합니다.

 

Outline을 보면 setChef() 함수가 생성되었고 Chef가 Autowired되어진것을 확인할수 있다 (onMethod 를 통해서)

 

 

1.XML 을 이용하는 의존성 주입설정

스프링에서 관리되는 객체를 흔히 빈(Bean)이라고 하고, 이에 대한 설정은 XML과 JAVA를 통해 처리가능.

프로젝트내에 SRC폴더 내 root-context.xml 은 스프링프레임워크에서 관리해야 하는 객체(이러한 객체를 빈(Bean)이라고 한다)를 설정하는 파일이다.

 

root-context.xml 내에 Namespaces

 

Namespace 에서 context를 추가한 후 Source 에서 
<context:component-scan base-package="org.zerock.sample"></context:component-scan>

를 추가하니 Spring Beans 에 restaurant와 chef (Bean)이 생성되었다.

 

이는 <context:component-scan base-package="org.zerock.sample"></context:component-scan> 에서 

org.zerock.sample 이라는 패키지 내에 빈(Bean)객체를 생성하라고 지정되어 있을경우 해당 어노테이션을 찾아 빈을 생성하게된다.

 

 

 

2. JAVA로 설정하는 의존성 주입

위에서 설정해던것을 JAVA로 설정하는 방법으로는

 

 

이다..

 

 

 

 

스프링이 동작하면서 생기는 일로는..

 

1. 스프링 프레임워크가 시작되면 먼저 스프링이 사용하는 메모리 영역을 만드는데 이를 Context라고 하며, 스프링에서는 ApplocationContext라는 이름의 객체가 만들어 집니다.

 

2. 스프링은 자신이 객체를 생성하고 관리해야 하는 객체들에 대한 설정이 필요한데. 이에 대한 설정이 root-context.xml이다.

 

3. root-context.xml에 설정되어 있는 <context component-scan> 태그의 내용을 통해서 "org.zerock.sample" 패키지를 스캔하기 시작한다..

 

4. 해당 패키지 내에 있는 클래스중에 스프링이 사용하는 @Component라는 어노테이션이 존재하는 클래스의 인스턴스를 생성한다.

 

5. Restaurant 객체는 Chef 객체가 필요하다는 어노테이션(@Autowired) 설정이 있으므로, 스프링은 Chef 객체의 레퍼런스를 Restaurant 객체에 주입합니다.

 

 

 

========================================

작성한 코드 테스트

1. 테스트 코드, 테스트 코드가 스프링을 실행하는 역할을 할 것이라는 것을 @Runwith 어노테이션으로 표시합니다.

2. @ContextConfiguration은 지정돈클래스나 문자열을 이용해서 필요한 객체들을 스프링 내에 객체로 등록하게 됩니다.

(스프링의 빈으로 등록된다고 표현한다.)

3.@ContextConfiguration에 사용하는 문자열은 " classpath: " "file: " 을 이용할 수 있으므로, 이클립스에서 자동으로 생성된 root-context.xml을 경로를 지정할 수 있다.

4. Log4j 는 로그설정

5.@Autowired는 해당 인스턴스 변수가 스프링으로부터 자동으로 주입해달라는 표시이며, 스프링은 정상적으로 주입이 가능하다면, obj 변수에 Restaurant 타입의 객체를 주입하게 됩니다.

6.@Test 는 JUnit에서 테스트 대상을 표시하는 어노테이션이다. 해당 메서드를 선택하고 JUnit Test기능을 실행한다.

7. assertNotNull() 은 restaurant 변수가 null이 아니여야만 테스트가 성공한다는 것을 의미,

 

 

 

Spring관련

  1. @Component는 해당 클래스가 스프링에서 객체로 만들어 관리하는 대상임을 명시하는 어노테이션. @ComponentScan을 통해서 지정되어 있으므로 basePackage에 해당되는 클래스를 조사하며, 어노테이션이 존재하는 클래스를 객체로 생성하여 빈(Bean)으로 관리하게 된다.
  2. Autowired는 스프링내부에서 자신이 특정한 객체에 의존적이므로 자신에게 해당 타입의 빈을 주입해주라는 표시로 위에서 Restaurant 객체는 Chef 타입의 객체가 필요한것을 명시함. 스프링은 Autowired를 보고 스프링내부에 관리되는 객체(빈:BEAN)을 확인하여 존재할경우 자동으로 주입해준다. 

   만약 Chef라는 객체가 Bean으로 관리되어 있찌 않다면,

java.lang.IllegalStateException: Failed to load ApplicationContext
at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:132)
at org.springframework.test.context.support.DefaultTestContext.getApplicationContext(DefaultTestContext.java:123)
at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.injectDependencies(DependencyInjectionTestExecutionListener.java:118)
at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.prepareTestInstance(DependencyInjectionTestExecutionListener.java:83)
at org.springframework.test.context.TestContextManager.prepareTestInstance(TestContextManager.java:244)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.createTest(SpringJUnit4ClassRunner.java:227)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner$1.runReflectiveCall(SpringJUnit4ClassRunner.java:289)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.methodBlock(SpringJUnit4ClassRunner.java:291)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:246)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:97)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61)
at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:70)
at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:190)
at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:89)
at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:40)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:541)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:768)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:464)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:210)
Caused by: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'restaurant': Unsatisfied dependency expressed through method 'setChef' parameter 0; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'org.zerock.sample.Chef' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {}
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredMethodElement.resolveMethodArguments(AutowiredAnnotationBeanPostProcessor.java:768)
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredMethodElement.inject(AutowiredAnnotationBeanPostProcessor.java:720)
at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:119)
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessProperties(AutowiredAnnotationBeanPostProcessor.java:399)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1425)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:593)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:516)
at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:324)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:322)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:202)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:897)
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:879)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:551)
at org.springframework.test.context.support.AbstractGenericContextLoader.loadContext(AbstractGenericContextLoader.java:127)
at org.springframework.test.context.support.AbstractGenericContextLoader.loadContext(AbstractGenericContextLoader.java:60)
at org.springframework.test.context.support.AbstractDelegatingSmartContextLoader.delegateLoading(AbstractDelegatingSmartContextLoader.java:275)
at org.springframework.test.context.support.AbstractDelegatingSmartContextLoader.loadContext(AbstractDelegatingSmartContextLoader.java:243)
at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContextInternal(DefaultCacheAwareContextLoaderDelegate.java:99)
at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:124)
... 25 more
Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'org.zerock.sample.Chef' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {}
at org.springframework.beans.factory.support.DefaultListableBeanFactory.raiseNoMatchingBeanFound(DefaultListableBeanFactory.java:1717)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1273)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1227)
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredMethodElement.resolveMethodArguments(AutowiredAnnotationBeanPostProcessor.java:760)
... 44 more

 * 빈(Bean)이 존재하지 않다고 에러가 발생한다.