@PostConstruct не вызывается в сочетании с программами чтения Spring Batch

Я пытался реализовать методы @PostConstruct и @PreDestroy в моем классе Account. Ни один из них не работал в следующей ситуации, но для краткости я буду говорить только о @PostConstruct.

Я использую программы чтения Spring Batch для загрузки этих учетных записей из файла фиксированной длины. Пока все хорошо, за исключением случаев, когда мой ридер создает эти учетные записи, он, по-видимому, не вызывает метод @PostConstruct (отладочные точки останова никогда не активируются, а сообщения журнала не распечатываются).
Читатель является пользовательским только в том смысле, что это пользовательский класс, расширяющий FlatFileItemReader<Account> и устанавливающий значения в конструкторе.

Добавление точно такого же метода инициализации (который никогда не вызывался в классе Account) к самому считывателю работает просто отлично.
Т.е. если метод @PostConstruct должен вызываться при инициализации reader, он работает. Только не тогда, когда читатель сам инициализирует учетные записи, аннотированные с помощью @PostConstruct.

Если я добавлю точку останова или сообщение журнала непосредственно в конструкторе Account, это также работает без проблем.


Является ли это желаемым поведением Spring Batch? Или это может быть вызвано какой-либо моей конфигурацией?

В ответе на другой вопрос упоминается, что такие аннотации, как @PostConstruct, "применяются только к bean-компонентам, управляемым контейнером" , а не если "вы просто звоните new BlogEntryDao() себе".

Это то, что здесь происходит - Spring Batch вызывает new Account(...) напрямую, не регистрируя их в контейнере? В конце концов, у меня никогда не было этих учетных записей в виде bean-компонентов или чего-то еще.


person PixelMaster    schedule 07.09.2018    source источник
comment
См. ответ @Ivans. Если Account представляет собой строку файла, то какую дополнительную логику необходимо выполнить в конструкции post или в методе pre destroy Account? Действительно ли эта логика принадлежит Account? Какова логика?   -  person Andrew S    schedule 07.09.2018
comment
В моем конкретном случае использования я просто хотел попробовать аннотации PostConstruct и PreDestroy и случайным образом выбрал этот класс. На самом деле я не уверен, есть ли реальный вариант использования, когда эти методы были бы предпочтительнее, чем еще один шаг в работе. Тем не менее, мне любопытно, почему они не называются.   -  person PixelMaster    schedule 07.09.2018


Ответы (2)


Ваш класс Account помечен @Component, @Bean или @Service? Если вы создаете объекты класса аккаунта типа Account c = new Account(), nSpring не знает о создании таких объектов. Из-за этого Spring не вызывает метод с аннотацией @postConstruct

person Ivan    schedule 07.09.2018
comment
Нет, мой класс Account не аннотирован @Component & Co. Тем не менее, я сам никогда не вызываю new Account(), создание учетных записей обрабатывается реализациями ItemReader, предоставляемыми Spring Batch по умолчанию. Я предполагаю, что проблема заключается где-то в этой реализации, я просто не уверен, что она не должна работать по замыслу или нет. - person PixelMaster; 07.09.2018
comment
Метод @PixelMaster PostConstruct вызывается только для объектов, созданных внутри контекста Spring контейнером Spring IoC. - person Ivan; 07.09.2018

когда мой читатель создает эти учетные записи, он, по-видимому, не вызывает метод @PostConstruct

Методы @PostConstruct и @PreDestroy вызываются контейнером Spring после создания и перед уничтожением экземпляра вашего компонента. Если ваш объект не управляется Spring, эти методы не будут вызываться.

Я использую программы чтения Spring Batch для загрузки этих учетных записей из файла фиксированной длины.

В этом случае вы уже должны были настроить FieldSetMapper для сопоставления полей с экземпляром Account. Если вы используете BeanWrapperFieldSetMapper, вы можете установить PrototypeBeanName, которое является именем bean-компонента (например, типа Account) прототипа области видимости (чтобы экземпляр создавался для каждой строки). Таким образом, экземпляры Account будут управляться Spring, использоваться средством чтения Spring Batch, и будет вызываться ваш метод с аннотацией PostConstruct. Вот пример:

@Bean
@Scope("prototype")
public Account account() {
    return new Account();
}

@Bean
public BeanWrapperFieldSetMapper<Account> beanMapper() {
    BeanWrapperFieldSetMapper<Account> fieldSetMapper = new BeanWrapperFieldSetMapper<>();
    fieldSetMapper.setPrototypeBeanName("account");
    return fieldSetMapper;
}

@Bean
public FlatFileItemReader<Account> accountReader() {
    return new FlatFileItemReaderBuilder<Account>()
            .name("accountsItemReader")
            .resource(new ClassPathResource("accounts.txt"))
            .fixedLength()
            .columns(new Range[] {new Range(1, 1), new Range(2, 4)})
            .names(new String[]{"id", "name"})
            .fieldSetMapper(beanMapper())
            .build();
}

Подробнее об этом читайте в Javadoc.

Надеюсь это поможет.

person Mahmoud Ben Hassine    schedule 10.09.2018