Spring

[Spring] 스프링 DI를 이용한 객체 생성(3)

재담 2022. 2. 10. 00:01

이전 글 : https://jaedam.tistory.com/7

 

[Spring] 스프링 DI를 이용한 객체 생성(2)

이전 글 : https://jaedam.tistory.com/5 [Spring] 스프링 DI를 이용한 객체 생성(1) DI란? DI는 Dependency Injection의 줄임말로서 의존성 주입이라고도 부른다. 스프링은 기본적으로 DI를 기반으로 동작하기 때..

jaedam.tistory.com

앞서 스프링 컨테이너의 종류와 XML 파일의 각 태그를 간략하게 살펴보았다.

이번 글에서는 자바 코드를 이용한 DI 설정에 대해서 살펴보자.

 

@Configuration과 @Bean을 이용한 빈 객체 설정

스프링은 @Configuration 어노테이션이 붙은 클래스를 설정 정보로 사용한다. 그리고 스프링이 제공할 빈 객체는 @Bean 어노테이션을 이용해서 지정한다.

@Configuration
public class Config {

    @Bean
    public User user1() {
        return new User("user1", "1234");
    }

    // 이하 생략
    ...
}

위 코드에서 user1() 메서드에 @Bean 어노테이션을 적용했는데, 이는 user1() 메서드가 생성하는 객체를 빈 객체로 사용하고 메서드 이름인 user1을 빈 객체의 이름으로 사용한다는 의미이다. @Configuration 설정 클래스를 이용해서 스프링 컨테이너를 생성할 때에는 AnnotationConfigApplicationContext 클래스를 사용한다.

 

AnnotationConfigApplicationContext 객체를 생성한 뒤에 @Bean 어노테이션으로 설정한 빈 정보를 이용해서 빈 객체를 구할 수 있다. 앞서 설명한 것처럼 메서드 이름인 "user1"을 식별값으로 빈을 구하고 있다.

AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(Config.class);
User user1 = ctx.getBean("user1", User.class);

 

빈 객체의 식별값으로 메서드 이름이 아닌 다른 이름으로 사용하고 싶다면 @Bean 어노테이션의 name 속성을 사용하면 된다. 아래 코드에서는 name 속성값으로 "user2"를 빈 객체의 식별값으로 사용하고 있다.

@Bean(name = "user2")
public User user() {
    return new User("user2", "qwer");
}

 

자바 코드로 의존 설정하기

생성자나 프로퍼티에 값을 설정할 때에는 코드에서 직접 설정해주면 된다.

@Bean
public User user1() {
    return new User("user1", "1234"); // 생성자에 값 직접 전달
}
    
@Bean
public AuthFailLogger authFailLogger() {
    AuthFailLogger logger = new AuthFailLogger();
    logger.setThreshold(2); // 프로퍼티에 값 직접 전달
    return logger;
}

 

다른 빈 객체를 참조해야 할 때에는, 참조할 빈 객체를 생성하는 메서드를 호출해서 빈 객체를 구하면 된다.

@Bean
public User user1() { ... }

@Bean(name = "user2")
public User user() { ... }

@Bean
public UserRepository userRepository() {
    UserRepository userRepo = new UserRepository();
    userRepo.setUsers(Arrays.asList(user1(), user())); // 메서드 직접 호출
    return userRepo;
}

위 코드에서 UserRepository 객체의 users 프로퍼티를 설정하기 위해 user1(), user() 메서드를 호출했는데, 이 코드는 다음과 같은 XML과 동일한 의존 설정을 하게 된다.

<bean id="userRepository" class="[패키지경로].UserRepository">
    <property name="users">
        <list>
            <ref bean="user1" /> <!-- user1() 메서드 호출과 일치 -->
            <ref bean="user2" /> <!-- user() 메서드 호출과 일치 -->
        </list>
    </property>
</bean>

 

참고로 빈 객체를 생성하는 메서드를 여러 번 호출하면 매번 새로운 객체를 생성할 것 같지만, 실제로 스프링에 의해 생성되는 객체는 항상 동일한 객체를 리턴한다. 이에 대해서는 다음 글을 참고하자.

참고 : https://jaedam.tistory.com/10

 

[Spring] 자바 설정 빈 객체 생성 방법

우선 다음 코드를 보자. @Configuration public class Config { @Bean public UserRepository userRepository() { ... } @Bean public PasswordChangeService pwChangeSvc() { return new PasswordChangeService(u..

jaedam.tistory.com

 

@Import 어노테이션을 이용한 조합

@Import 어노테이션을 이용해서 설정을 조합할 수 있다.

@Configuration
@Import(AnotherConfig.class)
public class Config {
    // 이하 생략
    ...
}

 

두 개 이상의 클래스를 지정하고 싶다면, @Import 어노테이션의 값으로 클래스 목록을 배열로 전달하면 된다.

@Configuration
@Import({OtherConfig.class, AnotherConfig.class})
public class Config {
    // 이하 생략
    ...
}

 

XML 설정 vs 자바 설정

XML 설정 특징

  • 설정 정보를 변경할 때에는 XML만 변경하면 된다.
  • 많은 프레임워크 / 라이브러리가 XML 스키마를 이용한 설정의 편리함을 지원한다.
  • IDE의 자동 완성 기능이 빈약하면 XML 작성 과정이 번거롭다.
  • 코드를 실행해야 설정 정보 오류를 확인 가능하다.

자바 설정 특징

  • 오타 및 설정 정보 오류를 미리 알 수 있다.(컴파일러)
  • IDE가 제공하는 자동 완성 기능의 도움을 받을 수 있다.
  • 설정이 바뀌면 자바 코드를 재컴파일해주어야 한다.
  • 프레임워크 / 라이브러리 중 아직 자바 기반의 편리한 설정을 지원하지 않는 경우가 있다.

각각의 장점이 서로 다르기 때문에 상황에 따라 알맞게 방식을 조합해서 사용해야 한다.


Reference

  • 웹 개발자를 위한 Spring 4.0 프로그래밍 (최범균 저)