포스트

Spring Boot - 특정 객체를 여러개의 bean으로 생성하기

객체 A를 조금씩 다른 속성을 가진 여러개의 bean으로 등록하고 사용하기 위해
@Bean 어노테이션의 name 속성 값과 @Qulifier(“bean name”) 어노테이션 조합을 이용하거나
@Bean 어노테이션의 name 속성 값과 인스턴스 이름을 같게 하는 것을 이용하는 조합으로 사용해볼 수 있다.


실습 1.

@Bean(name) + @Qualifier("bean name") 사용

이 조합을 사용할 때 주의할 점은 기본으로 사용될 Bean에 @Primary 어노테이션을 붙여줘야 하는 것이다.

만약 기본으로 사용될 bean에 @Primary 어노테이션을 붙이고 싶지 않다면 모든 bean에 name 값을 작성해주어야 하고 인스턴스 생성 시 이름을 bean 이름과 똑같게 해주어야 한다.

@Primary 어노테이션을 bean 선언시 붙여주게 되면 인스턴스 생성 시 @Primary @Bean 객체와 이름을 다르게 붙여주어도 @Primary @Bean이 주입되기 때문에 코드 작성에 조금 더 유연해진다.

ObjectMapper 객체 2개의 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
@Configuration  
public class ObjectMapperConfig {  

    @Bean  
    @Primary
    public ObjectMapper objectMapper() {  
        return setObjectMapperConfig(new ObjectMapper(), false);  
    }  
    
    @Bean(name = "objectMapperWithTimestamp")  
    public ObjectMapper objectMapperWithTimestamp() {  
        return setObjectMapperConfig(new ObjectMapper(), true);  
    }  
    
    private ObjectMapper setObjectMapperConfig(ObjectMapper objectMapper, boolean enableTimestamp) {  
        objectMapper.registerModule(new Jdk8Module()); 
        objectMapper.registerModule(new JavaTimeModule()); 
        objectMapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, enableTimestamp);
        objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); 
        objectMapper.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false); 
        objectMapper.setPropertyNamingStrategy(new PropertyNamingStrategies.SnakeCaseStrategy()); 
        return objectMapper;  
    }  
}


test

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
@SpringBootTest  
public class ObjectMapperTest {  
    @Autowired  
    @Qualifier("objectMapperWithTimestamp")  
    ObjectMapper objectMapperWithTimestamp;  
      
    @Autowired  
    ObjectMapper objectMapper;  
    
    @Autowired  
    ObjectMapper mapper;  
      
    @Test  
    void test() throws JsonProcessingException {  
        Object temp = new Object() {  
            public final String name = "test";  
            public final LocalDateTime createdAt = LocalDateTime.now();  
        };  
          
        String getTempWithTimestamp = objectMapperWithTimestamp.writeValueAsString(temp);  
        System.out.println(getTempWithTimestamp);  
          
        String getTemp = objectMapper.writeValueAsString(temp);  
        System.out.println(getTemp);  
        
        String getTemp2 = mapper.writeValueAsString(temp);  
        System.out.println(getTemp2);  
    }  
}

실행 값

1
2
3
{"name":"test","created_at":[2024,7,3,6,58,35,403181300]}
{"name":"test","created_at":"2024-07-03T06:58:35.4031813"}
{"name":"test","created_at":"2024-07-03T06:58:35.4031813"}


Lombok + @Qualifier

Lombok 사용 시 @RequireArgsConstructor 어노테이션을 통해 생성자 주입을 받도록 사용하는 경우, @Qualifier 어노테이션은 생성자 주입에 사용되지 않도록 기본 설정이 되어있다.

@Qualifier 어노테이션이 생성자 주입시 사용되게 하려면 Lombok 설정파일을 작성하여 설정해줘야 한다.

- Lombok 설정 파일 작성

프로젝트 루트 위치에 lombok.config 파일을 생성하고 아래 내용을 작성

1
lombok.copyableAnnotations += org.springframework.beans.factory.annotation.Qualifier


실습 2.

@Bean(name) + 인스턴스 이름 = 'bean name' 조합으로 사용

이 조합을 사용할 때 주의할 점은 다음과 같다.

  1. 생성하는 bean의 이름을 모두 작성해줘야 하는 것
  2. bean 이름과 인스턴스 이름을 똑같게 지정하는 것

이 경우 @Qulifier 어노테이션을 사용하지 않기 때문에
bean 생성시 기본으로 사용될 bean에 @Primary를 붙여주게 되면 인스턴스 이름을 각각의 bean 이름과 같게 작성해도 전부 @Primary가 붙은 bean이 주입 된다는 점에 주의해야 한다.

ObjectMapper 객체 2개의 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 ObjectMapperConfig {  

    @Bean(name = "objectMapper")
    public ObjectMapper objectMapper() {  
        return setObjectMapperConfig(new ObjectMapper(), false);  
    }  
    
    @Bean(name = "objectMapperWithTimestamp")  
    public ObjectMapper objectMapperWithTimestamp() {  
        return setObjectMapperConfig(new ObjectMapper(), true);  
    }  
    
    private ObjectMapper setObjectMapperConfig(ObjectMapper objectMapper, boolean enableTimestamp) {  
        objectMapper.registerModule(new Jdk8Module()); 
        objectMapper.registerModule(new JavaTimeModule()); 
        objectMapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, enableTimestamp);
        objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); 
        objectMapper.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false); 
        objectMapper.setPropertyNamingStrategy(new PropertyNamingStrategies.SnakeCaseStrategy()); 
        return objectMapper;  
    }  
}


test

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
@SpringBootTest  
public class ObjectMapperTest {  
    @Autowired  
    ObjectMapper objectMapperWithTimestamp;  
      
    @Autowired  
    ObjectMapper objectMapper;  
      
    @Test  
    void test() throws JsonProcessingException {  
        Object temp = new Object() {  
            public final String name = "test";  
            public final LocalDateTime createdAt = LocalDateTime.now();  
        };  
          
        String getTempWithTimestamp = objectMapperWithTimestamp.writeValueAsString(temp);  
        System.out.println(getTempWithTimestamp);  
          
        String getTemp = objectMapper.writeValueAsString(temp);  
        System.out.println(getTemp);  
    }  
}

실행 값

1
2
{"name":"test","created_at":[2024,7,3,6,58,35,403181300]}
{"name":"test","created_at":"2024-07-03T06:58:35.4031813"}




참고한 사이트

이 기사는 저작권자의 CC BY 4.0 라이센스를 따릅니다.