Как преобразовать объект с помощью ObjectMapper и ввести в него зависимости

Я пытаюсь преобразовать Object в конкретный класс с помощью jackson ObjectMapper и ввести зависимости после его преобразования. Вот пример:

public class SimpleClass{
    private String parameter;
    @JsonIgnore
    private SomeService service;

    /** getters and setters **/
    public void doSomethingFromService(){
        //call some methods from the service
    }
}

После попытки десериализации объекта (значение - карта, содержащая параметры):

ObjectMapper om = new ObjectMapper();
om.convertValue(value,SimpleClass.class).doSomethingFromService();

-> привести к исключению NullPointerException ... Как внедрить услугу?

Могу ли я получить службу из контекста и внедрить ее в конструктор по умолчанию?

Джексон - это среда де / сериализации JSON / XML, а не CDI.

rkosegi 08.06.2018 16:46
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
0
1
970
4
Перейти к ответу Данный вопрос помечен как решенный

Ответы 4

Это невозможно. Только объекты, экземпляры которых были созданы с помощью Spring, могут использовать @Autowired.

Это просто: когда вы аннотируете объект с помощью @Service, spring попытается разрешить все его зависимости с помощью интроспекции.

С Джексоном (или если вы пытаетесь создать экземпляр объекта самостоятельно) вы полностью выходите за рамки Spring.

И я должен был знать, что то, что вы пытаетесь сделать (даже если бы это было возможно), не является хорошей практикой. Не следует смешивать объекты данных с бизнес-обработкой.

Я понимаю это, но могу ли я ввести его, например, в конструктор по умолчанию? Не обязательно использовать аннотацию с автоматическим подключением для вставки bean-компонента.

xyz 08.06.2018 16:42

@xyz Невозможно, поскольку Jackson потребности пустой конструктор.

NiVeR 08.06.2018 16:43

Вы всегда можете добавить сеттер для своего сервиса. Но зачем вам это делать? Вы не должны получать такие объекты извне вашего приложения.

Oreste Viron 08.06.2018 16:47

например, если служба проверяет dto

xyz 08.06.2018 16:50

Если служба проверяет только dto, вы можете использовать чистые функции вместо использования службы (или использовать библиотеки проверки, уже интегрированные в spring и jax-rs, например hibernate-validator).

Oreste Viron 08.06.2018 16:52

Как было сказано ранее, внедрение сервисов возможно только с такими фреймворками, как Spring.

Если вы используете Spring, аннотируйте свой класс службы с помощью @Service, а затем, в отличие от использования @Autowired, объявите свою службу закрытым финалом и введите его с помощью конструктора (IMO, я считаю, что это работает лучше).

Если вы не используете Spring, вам нужно создать новый экземпляр службы, а затем вызвать этот экземпляр - если, конечно, это не статический ...

Джексону нужны пустые конструкторы.

Oreste Viron 08.06.2018 16:48

Если вы выполняли инициализацию объекта SimpleClass самостоятельно, вы можете заставить его работать, автоматически подключив частичный экземпляр с помощью AutowireCapableBeanFactory, в этом случае @Autowrire службы будет работать, поскольку Spring также управляет частичным экземпляром объекта SomeClass.

Тем не менее, это не выход. Объекты данных должны быть изолированы от бизнес-логики.

Вернемся к вашему случаю, вы не можете автоматически подключать даже так, как я говорил, потому что Джексон является поставщиком экземпляра, а Джексон требует - наличие пустого конструктора.

Ответ принят как подходящий

Поскольку вам нужно какое-то автоматическое подключение в вашем компоненте SimpleClass, вам необходимо аннотировать его свойство SomeService service с помощью @Autowired.

public class SimpleClass {

    private String parameter;

    @JsonIgnore
    @Autowired
    private SomeService service;

    // getter and setter for parameter (omitted here for brevity)

    public void doSomethingFromService(){
        //call some methods from the service
    }
}

Как уже говорили другие, ObjectMapper не выполняет инъекцию зависимостей. Но можно комбинировать @Autowired с игнорированием ObjectMapper с некоторым запускаемым вручную автоматическим подключением.

Для этого вам понадобится AutowireCapableBeanFactory, который вы получите от Spring нормальная инъекция зависимости с @Autowired. Затем вы используете его метод autowireBean(Object) чтобы внедрить свойства @Autowired bean-компонента.

@Autowired
private  AutowireCapableBeanFactory autowireCapableBeanFactory;

public void doSomething(Map<String, Object> value) throws Exception {
    ObjectMapper om = new ObjectMapper();
    SimpleClass bean = om.convertValue(value, SimpleClass.class);
    autowireCapableBeanFactory.autowireBean(bean);
    bean.doSomethingFromService();
}

Другие вопросы по теме