[英]@PostConstruct fails to be called when combined with Spring Batch readers
I've been trying to implement @PostConstruct
and @PreDestroy
methods in an Account
class of mine. 我一直在尝试在我的
Account
类中实现@PostConstruct
和@PreDestroy
方法。 Neither of them worked in the following situation, but for the sake of brevity, I'll only talk about @PostConstruct
. 他们都不在以下情况下工作,但是为了简洁起见,我只谈论
@PostConstruct
。
I'm using Spring Batch's readers to load these accounts from a fixed-length file. 我正在使用Spring Batch的阅读器从固定长度的文件加载这些帐户。 So far, so good, except when my reader creates these accounts, it apparently does not call the
@PostConstruct
method (debug breakpoints are never activated, and log messages are not printed out). 到目前为止,一切都很好,除非我的读者创建了这些帐户,否则它显然不会调用
@PostConstruct
方法(永远不会激活调试断点,并且不会输出日志消息)。
The reader is only custom in the sense that it's a custom class extending FlatFileItemReader<Account>
and setting values in the constructor. 读者是自定义的,这是因为它是扩展
FlatFileItemReader<Account>
并在构造函数中设置值的自定义类。
Adding the exact same initialization method (that never got called in the Account
class) to the reader itself works just fine. 将完全相同的初始化方法(在
Account
类中从未调用过)添加到读取器本身即可正常工作。
Ie if the @PostConstruct
method should be called upon reader initialization, it works. 即,如果应该在读取器初始化时调用
@PostConstruct
方法,它将起作用。 Just not when the reader itself initializes accounts annotated with @PostConstruct
. 只是当读者自己初始化带有
@PostConstruct
注释的帐户时,才不会。
If I add a breakpoint or log message in the constructor of Account
directly, it also works without an issue. 如果直接在
Account
的构造函数中添加断点或日志消息,它也可以正常工作。
Another question's answer mentioned that annotations such as @PostConstruct
"only apply to container-managed beans", not if "you are simply calling new BlogEntryDao()
yourself". 另一个问题的回答提到了注释,比如
@PostConstruct
“仅适用于容器管理豆”,如果不是“你只是调用new BlogEntryDao()
自己”。
Is this what's happening here - Spring Batch calling new Account(...)
directly, without registering them in the container? 这是这里发生的事情吗-Spring Batch直接调用
new Account(...)
,而无需在容器中注册它们? After all, I never have these accounts available as beans or anything. 毕竟,我从来没有将这些帐户用作bean或其他任何东西。
Is your Account
class annotated with @Component
, @Bean
or @Service
? 是否使用
@Component
@Bean
, @Service
@Bean
或@Service
注释您的Account
类? If you create objects of account class like Account c = new Account()
the nSpring doesn't know about creation of such objects. 如果您创建帐户类的对象,例如
Account c = new Account()
则nSpring不会创建此类对象。 Because of that Spring doesn't call method annotated with @postConstruct
因此,Spring不会调用以
@postConstruct
注释的方法
when my reader creates these accounts, it apparently does not call the @PostConstruct method
当我的读者创建这些帐户时,它显然未调用@PostConstruct方法
@PostConstruct
and @PreDestroy
methods are called by the Spring container after creating and before destroying the instance of your bean. 在创建容器之后并销毁bean实例之前,Spring容器将调用
@PostConstruct
和@PreDestroy
方法。 If your object is not managed by Spring, those methods will not be called. 如果您的对象不是由Spring管理的,则不会调用这些方法。
I'm using Spring Batch's readers to load these accounts from a fixed-length file
我正在使用Spring Batch的阅读器从固定长度的文件加载这些帐户
In this case, you should have already configured a FieldSetMapper
to map fields to an Account
instance. 在这种情况下,您应该已经配置了
FieldSetMapper
以将字段映射到Account
实例。 If you use the BeanWrapperFieldSetMapper
, you can set the PrototypeBeanName
which is the name of a bean (for example of type Account
) of scope prototype (so that an instance is created for each line). 如果使用
BeanWrapperFieldSetMapper
,则可以设置PrototypeBeanName
,它是作用域原型的Bean(例如Account
类型)的名称(以便为每行创建一个实例)。 This way, Account
instances will be managed by Spring, used by Spring Batch reader, and your method annotated with PostConstruct
will be called. 这样,
Account
实例将由Spring管理,由Spring Batch阅读器使用,并且将调用用PostConstruct
注释的方法。 Here is an example: 这是一个例子:
@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();
}
More details about this in the Javadoc . Javadoc中对此有更多详细信息。
Hope this helps. 希望这可以帮助。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.