yahayaha

1. Setter 메서드 사용해서 의존성 주입 해보기 본문

spring/환경설정

1. Setter 메서드 사용해서 의존성 주입 해보기

yaha 2024. 1. 11. 22:45

스프링 동작 테스트를 할 것이라 pom.xml에서 Lombok 라이브러리를 추가하고, 

 

spring-test 라이브러리를 사용하려함.

 

먼저 pom.xml에서 추가를 하거나 변경할 라이브러리들이 존재함.

 

		<dependency>
  		  	<groupId>org.springframework</groupId>
  			<artifactId>spring-test</artifactId>
   			<version>${org.springframework-version}</version>
       		</dependency> 
            
       	 	<dependency>
			<groupId>junit</groupId>
			<artifactId>junit</artifactId>
			<version>4.12</version>
			<scope>test</scope>
		</dependency> 

		<dependency>
			<groupId>org.projectlombok</groupId>
			<artifactId>lombok</artifactId>
			<version>1.18.0</version>
			<scope>provided</scope>
		</dependency>
        
        	<dependency>
			<groupId>log4j</groupId>
			<artifactId>log4j</artifactId>
			<version>1.2.17</version>
			<!-- log4j -->
        	</dependency>

 

spring에서 생성된 프로젝트의 Log4j 라이브러리는 1.2.15버전으로 설정 되어있는데 이걸 1.2.17버전으로 수정을 해야함.

( lombok을 사용할 때 문제가 생길 수 있음, )

 

그럼 일단 예제 클래스를 생성.

 

 

일반적으로 스프링에서의 의존성 주입은 Chef를 클래스가 아닌 인터페이스로 설계하는 것이 좋지만,

 

지금은 최소한의 코드만 사용해서 의존성 주입을 테스트 하는 목적이기에 클래스로 설계

 

chef클래스를 다음과 같이 작성.

import org.springframework.stereotype.Component;

import lombok.Data;


@Component
@Data
public class Chef {


}

 

Restaurant 클래스는 chef를 주입받도록 설계 하기에 이때 Lombok의 setter를 생성하는 기능과 생성자, toString() 등을 자동으로 생성하도록 @Data 어노테이션을 사용

 

그리고 Restaurant클래스를 작성.

 

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import lombok.Data;
import lombok.Setter;

@Component
@Data
public class Restaurant {

	
	@Setter(onMethod_ = @Autowired)
	private Chef chef;
}

 

작성된 코드가 의미하는것

1. Restaurant 객체는 Chef 타입의 객체를 필요한 상황

2. @Component는 스프링에 해당되는 클래스가 스프링에서 관리해야하는 대상을 표시하는 어노테이션.

3. @Setter는 자동적으로 setChef()를 컴파일 시 생성

4. @Setter에서 사용된 onMethod 속성은 생성된 setChef()에 @Autowired 어노테이션 추가.

5. Lombok으로 생성된 클래스에 이클립스를 통해서 확인.

Lombod으로 생성된 클래스 정보

 

테스트 코드를 통해서 확인 해보기.

프로젝트 내 ' src/test/java ' 폴대 내에 클래스 추가.

SampleTests 클래스는 spring-test 모듈을 이용해서 간단하게 스프링 가동.

 

이때 반드시 Junit은 4.10 이상의 버전을 사용

 

import static org.junit.Assert.assertNotNull;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

import lombok.Setter;
import lombok.extern.log4j.Log4j;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("file:src/main/webapp/WEB-INF/spring/root-context.xml")
@Log4j
public class SampleTests {

	@Setter(onMethod_ = {@Autowired})
	private Restaurant restaurant;
	
	@Test
	public void testExist() {
		
		assertNotNull(restaurant);
		
		log.info(restaurant);
		log.info("-------------------");
		log.info(restaurant.getChef());

	}
}

 

테스트 코드는 우선 현재 테스트 코드가 스프링을 실행하는 역할을 할 것이라는 것을 @Runwith 어노테이션으로 선언

 

다음으로 중요한 설정은 @ContextConfiguration 어노테이션과 속성값인 문자열 설정임.

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

( 이걸 흔히 스프링의 빈으로 등록 되었다고 표현함. )

 

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

 

@Log4j는 Lombok을 이용해서 로그를 기록하는 Logger를 변수로 생성함.

Logger 객체의 선언 없이도 Log4j 라이브러리와 설정이 존재한다면 바로 사용 가능.

 

@Autowirde는 해당 인스턴스 변수가 스프링으로 부터 자동으로 주입해 달라는 표시.

스프링은 정상적으로 주입이 가능하다면 obj변수에 Restaurant 타입의 객체를 주입하게됨

 

testExist()에 선언되어 있는 @Test는 JUnit에서 테스트 대상을 표시하는 어노테이션

해당 메서드를 선택하고 JUnit에서 기능을 실행

 

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

 

이러한 테스트 작업은 프로젝트 초기에 설정해 두고 사용하는 습관을 가지는게 좋음.

 

해당 테스트는 Run As > Junit Test를 실행.

testExist를 더블클릭 하고 오른쪽 클릭 해야함

 

테스트 결과가 의미하는 바는 스프링을 공부하는 데 있어서 가장 중요한 내용

 

1. 테스트 코드가 실행되기 위해서 스프링 프레임워크가 동작.

2. 동작하는 과정에서 필요한 객체들이 스프링에 등록.

3. 의존성 주입이 필요한 객체는 자동으로 주입이 이루어짐.

위 세가지 를 정리해 둘 필요가 있음.

 

코드에 사용된 어노테이션들을 정리해보자

 

Lombok 관련 어노테이션 Spring 관련 어노테이션 테스트 관련 어노테이션
@Setter

@Data

@Log4j
@Autowired

@Component
@RunWith

@ContextConfiguration

@Test

 

 

 

Lombok 관련 정리

@Setter

setter 메서드를 만들어주는 역할

 

@Setter에는 3가지 속성을 부여 할 수 있음.

속성명 의미
value 접근 제한 속성을 의미함.
기본값은 lombok.AccessLevel.PUBLIC
onMethod setter 메서드의 생성 시 메서드에 추가할 어노테이션을 지정

예제는 @Autowired라는 어노테이션이 지정되도록 장성.
코드는 특이하게'_' 표기가 사용되는데 JDK 버전에 따라 차이가 있음

up to JDK7:
@Setter(onMethod=@__({@AnnotarionsGoHere}))

up to JDK8:
@Setter(onMethod_=({@AnnotarionsGoHere}))
onparam setter 메서드의 파라미터에 어노테이션을
사용하는 경우에 적용

 

 

 

@Data

@Data는 Lombok에서 가장 자주 사용되는 어노테이션.

 

@Data는 @ToString, @EqualsAndHashCode, @Getter/@Setter, @RequiredArgsConstructor를

모두 결합한 형태로 한 번에 자주 사용되는 모든 메서드를 생성할 수 있다는 장점이 있음.

 

만일 세부적인 설정이 필요 없는 경우라면 @Data를 주로 이용함

 

@Log4j

로그 객체를 생성하게됨. 

 

 

Spring 관련

 

@Component

해당 클래스가 스프링에서 객체로 만들어서 관리하는 대상을 명시하는 어노테이션.

 

@Autowired

스프링 내부에서 자신이 특정한 객체에 의존적으로 자신에게 해당 타입의 빈을 주입해주라는 표시

 

위 Restaurant 객체는 Chef 타입의 객체가 필요하다는 것을 명시.

 

스프링은 @Autowired 어노테이션을 보고 스프링 내부에 관리하는 객체(들) 중에 적당한 것이 있는지를 확인하고 자동으로 주입해줌.

 

필요한 객체가 존재하지 않는다면 스프링은 제대로 객체 구성할 수 없기에 에러가 나옴.

 

Test 관련

테스트 관련해서 가장 중요한 어노테이션은 @ContextConfiguration임.

@ContextConfiguration은 스프링이 실행되면서 어떤 설정 정보를 읽어 들여야 하는지 명시함.

 

속성으로 locations를 이용해서 문자열의 배열로 XML, 설정 파일을 명시할 수 도 있음. classes 속성으로 

@Configuration이 적용된 클래스를 지정해 줄 수도 있음. @Runwith는 테스트 시 필요한 클래스를 지정함.

 

스프링은 SpringJUnit4ClassRunner 클래스가 해당됨. 

@Test는 junit에서 해당 메서드가 junit 상에서 단위 테스트의 대상인지 알려줌.

 

 

 

 

 

------------------------------------------------------------------------------------------------------------------------------------------------

 

테스트 공부 중 뻘짓

 

테스트를 실행하는 도중 오류가 발생.

​

INFO : org.springframework.test.context.support.DefaultTestContextBootstrapper - Loaded default TestExecutionListener class names from location [META-INF/spring.factories]: [org.springframework.test.context.web.ServletTestExecutionListener, org.springframework.test.context.support.DirtiesContextBeforeModesTestExecutionListener, org.springframework.test.context.support.DependencyInjectionTestExecutionListener, org.springframework.test.context.support.DirtiesContextTestExecutionListener, org.springframework.test.context.transaction.TransactionalTestExecutionListener, org.springframework.test.context.jdbc.SqlScriptsTestExecutionListener]

INFO : org.springframework.test.context.support.DefaultTestContextBootstrapper - Using TestExecutionListeners: [org.springframework.test.context.web.ServletTestExecutionListener@6c779568, org.springframework.test.context.support.DirtiesContextBeforeModesTestExecutionListener@f381794, org.springframework.test.context.support.DependencyInjectionTestExecutionListener@2cdd0d4b, org.springframework.test.context.support.DirtiesContextTestExecutionListener@7e9131d5]

INFO : org.springframework.beans.factory.xml.XmlBeanDefinitionReader - Loading XML bean definitions from URL [file:src/main/webapp/WEB-INF/spring/root-context.xml]

INFO : org.springframework.context.support.GenericApplicationContext - Refreshing org.springframework.context.support.GenericApplicationContext@fa49800: startup date [Wed Jan 10 21:53:08 KST 2024]; root of context hierarchy

INFO : org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor - JSR-330 'javax.inject.Inject' annotation found and supported for autowiring

INFO : org.springframework.context.support.GenericApplicationContext - Closing org.springframework.context.support.GenericApplicationContext@fa49800: startup date [Wed Jan 10 21:53:08 KST 2024]; root of context hierarchy

 

 

이유가 왜 그런지 찾아보고 질문 해서 얻은 답. 

 

Restaurant에만 있어야하는 객체가 Chef 객체에도 똑같은 코드를 입력해 가지고 순환참조가 되어 오류가 난 것.

 

다음부터는 책을 잘 보면서 해야할듯...

 

'spring > 환경설정' 카테고리의 다른 글

5-1. MyBatis 스프링 연동 (1)  (0) 2024.01.14
4. 커넥션 풀 설정하기(HikariCP)  (0) 2024.01.14
3. JDBC 연결하기.  (0) 2024.01.13
2. Oracle Database 연동 하기  (2) 2024.01.13
0. 목적  (1) 2024.01.11