[SPRING] JsonDeserializer에서의 Autowiring : SpringBeanAutowiringSupport 대 HandlerInstantiator
SPRINGJsonDeserializer에서의 Autowiring : SpringBeanAutowiringSupport 대 HandlerInstantiator
다음과 같이 autowired 서비스를 포함하는 사용자 정의 JsonDeserializer를 작성했습니다.
public class PersonDeserializer extends JsonDeserializer<Person> {
@Autowired
PersonService personService;
@Override
public Person deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException, JsonProcessingException {
// deserialization occurs here which makes use of personService
return person;
}
}
처음이 디시리얼라이저를 사용했을 때 personService가 자동 실행되고 있지 않은 것처럼 NPE를 얻었습니다. 다른 SO 답변 (특히,이 하나)에서 볼 때 autowiring이 작동하도록하는 두 가지 방법이 나타납니다.
옵션 1은 커스텀 디시리얼라이저의 생성자 내에서 SpringBeanAutowiringSupport를 사용하는 것입니다.
public PersonDeserializer() {
SpringBeanAutowiringSupport.processInjectionBasedOnCurrentContext(this);
}
옵션 2는 HandlerInstantiator를 사용하고 그것을 내 ObjectMapper 빈에 등록하는 것입니다 :
@Component
public class SpringBeanHandlerInstantiator extends HandlerInstantiator {
@Autowired
private ApplicationContext applicationContext;
@Override
public JsonDeserializer<?> deserializerInstance(DeserializationConfig config, Annotated annotated, Class<? extends JsonDeserializer<?>> deserClass) {
try {
return (JsonDeserializer<?>) applicationContext.getBean(deserClass);
} catch (Exception e) {
// Return null and let the default behavior happen
return null;
}
}
}
@Configuration
public class JacksonConfiguration {
@Autowired
SpringBeanHandlerInstantiator springBeanHandlerInstantiator;
@Bean
public ObjectMapper objectMapper() {
Jackson2ObjectMapperFactoryBean jackson2ObjectMapperFactoryBean = new Jackson2ObjectMapperFactoryBean();
jackson2ObjectMapperFactoryBean.afterPropertiesSet();
ObjectMapper objectMapper = jackson2ObjectMapperFactoryBean.getObject();
// add the custom handler instantiator
objectMapper.setHandlerInstantiator(springBeanHandlerInstantiator);
return objectMapper;
}
}
나는 두 가지 옵션을 모두 시도했으며 똑같이 잘 작동합니다. SpringBeanAutowiringSupport를 HandlerInstantiator 접근 방식과 비교할 때 어떤 단점이 있습니까? 분명히 옵션 3은 코드가 3 줄이기 때문에 훨씬 쉽습니다. 차이가 나는 경우에는 분당 수백 개의 객체를 비 직렬화 할 것입니다.
모든 조언 / 의견을 보내 주시면 감사하겠습니다.
해결법
-
==============================
1.Amir Jamak의 대답에 SpringHandlerInstantiator 인 Spring이 있으므로 사용자 정의 HandlerInstantiator를 만들 필요가 없습니다.
Amir Jamak의 대답에 SpringHandlerInstantiator 인 Spring이 있으므로 사용자 정의 HandlerInstantiator를 만들 필요가 없습니다.
스프링 구성에서 Jackson2ObjectMapperBuilder에 연결해야합니다.
@Bean public HandlerInstantiator handlerInstantiator(ApplicationContext applicationContext) { return new SpringHandlerInstantiator(applicationContext.getAutowireCapableBeanFactory()); } @Bean public Jackson2ObjectMapperBuilder objectMapperBuilder(HandlerInstantiator handlerInstantiator) { Jackson2ObjectMapperBuilder builder = new Jackson2ObjectMapperBuilder(); builder.handlerInstantiator(handlerInstantiator); return builder; }
-
==============================
2.이 주석에서 제안하고이 링크에서 발견되는대로 사용자 정의 HandlerInstantiator를 만들어야합니다.
이 주석에서 제안하고이 링크에서 발견되는대로 사용자 정의 HandlerInstantiator를 만들어야합니다.
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.ApplicationContext; import org.springframework.stereotype.Component; import com.fasterxml.jackson.databind.DeserializationConfig; import com.fasterxml.jackson.databind.JsonDeserializer; import com.fasterxml.jackson.databind.JsonSerializer; import com.fasterxml.jackson.databind.KeyDeserializer; import com.fasterxml.jackson.databind.SerializationConfig; import com.fasterxml.jackson.databind.cfg.HandlerInstantiator; import com.fasterxml.jackson.databind.cfg.MapperConfig; import com.fasterxml.jackson.databind.introspect.Annotated; import com.fasterxml.jackson.databind.jsontype.TypeIdResolver; import com.fasterxml.jackson.databind.jsontype.TypeResolverBuilder; @Component public class SpringBeanHandlerInstantiator extends HandlerInstantiator { private ApplicationContext applicationContext; @Autowired public SpringBeanHandlerInstantiator(ApplicationContext applicationContext) { this.applicationContext = applicationContext; } @Override public JsonDeserializer<?> deserializerInstance(DeserializationConfig config, Annotated annotated, Class<?> deserClass) { try { return (JsonDeserializer<?>) applicationContext.getBean(deserClass); } catch (Exception e) { // Return null and let the default behavior happen } return null; } @Override public KeyDeserializer keyDeserializerInstance(DeserializationConfig config, Annotated annotated, Class<?> keyDeserClass) { try { return (KeyDeserializer) applicationContext.getBean(keyDeserClass); } catch (Exception e) { // Return null and let the default behavior happen } return null; } @Override public JsonSerializer<?> serializerInstance(SerializationConfig config, Annotated annotated, Class<?> serClass) { try { return (JsonSerializer<?>) applicationContext.getBean(serClass); } catch (Exception e) { // Return null and let the default behavior happen } return null; } @Override public TypeResolverBuilder<?> typeResolverBuilderInstance(MapperConfig<?> config, Annotated annotated, Class<?> builderClass) { try { return (TypeResolverBuilder<?>) applicationContext.getBean(builderClass); } catch (Exception e) { // Return null and let the default behavior happen } return null; } @Override public TypeIdResolver typeIdResolverInstance(MapperConfig<?> config, Annotated annotated, Class<?> resolverClass) { try { return (TypeIdResolver) applicationContext.getBean(resolverClass); } catch (Exception e) { // Return null and let the default behavior happen } return null; } }
사용자 정의 ObjectMapper :
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.ApplicationContext; import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.databind.DeserializationFeature; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.SerializationFeature; import com.fasterxml.jackson.databind.cfg.HandlerInstantiator; public class CustomObjectMapper extends ObjectMapper { private static final long serialVersionUID = -8865944893878900100L; @Autowired ApplicationContext applicationContext; public JamaxObjectMapper() { // Problems serializing Hibernate lazily initialized collections? Fix here. // HibernateModule hm = new HibernateModule(); // hm.configure(com.fasterxml.jackson.module.hibernate.HibernateModule.Feature.FORCE_LAZY_LOADING, true); // this.registerModule(hm); // Jackson confused by what to set or by extra properties? Fix it. this.setSerializationInclusion(JsonInclude.Include.NON_NULL); this.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); this.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false); } @Override @Autowired public Object setHandlerInstantiator(HandlerInstantiator hi) { return super.setHandlerInstantiator(hi); } }
사용자 정의 ObjectMapper를 등록하십시오.
<bean id="jacksonObjectMapper" class="com.acme.CustomObjectMapper" /> <bean id="jacksonMessageConverter" class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter"> <property name="prefixJson" value="false" /> <property name="supportedMediaTypes" value="application/json" /> <property name="objectMapper" ref="jacksonObjectMapper" /> </bean>
이 순간에 다음을 사용할 수 있습니다 :
@JsonDeserialize(contentUsing=PersonDeserializer.class) public void setPerson(Person person) { ... }
... 및 personService는 null이 아닙니다.
-
==============================
3.봄 부팅을 사용하여 위의 답변 정리,
봄 부팅을 사용하여 위의 답변 정리,
@Bean public HandlerInstantiator handlerInstantiator(ApplicationContext context) { return new SpringHandlerInstantiator(context.getAutowireCapableBeanFactory()); } @Bean public ObjectMapper objectMapper(HandlerInstantiator handlerInstantiator) { Jackson2ObjectMapperBuilder builder = new Jackson2ObjectMapperBuilder(); builder.handlerInstantiator(handlerInstantiator); return builder.build(); }
from https://stackoverflow.com/questions/28393599/autowiring-in-jsondeserializer-springbeanautowiringsupport-vs-handlerinstantiat by cc-by-sa and MIT license
'SPRING' 카테고리의 다른 글
[SPRING] anglejs 앱에서 보낸 iOS에 PDF (Blob)를 표시하는 방법 (0) | 2019.01.31 |
---|---|
[SPRING] EntityListeners에 EntityManager를 삽입하는 방법 (0) | 2019.01.31 |
[SPRING] Spring-Boot : tomcat 커넥터를 추가하여 컨트롤러에 바인딩하는 방법 (0) | 2019.01.31 |
[SPRING] Hibernate JPA를 사용한 작업 단위 처리 문제 (0) | 2019.01.31 |
[SPRING] 스프링 부트를 사용하는 동안 스프링 배치 범위 문제 (0) | 2019.01.31 |