【发布时间】:2011-12-15 11:15:04
【问题描述】:
在Spring XML配置中使用@PostConstruct注解和声明与init-method相同的方法有什么区别吗?
【问题讨论】:
标签: spring
在Spring XML配置中使用@PostConstruct注解和声明与init-method相同的方法有什么区别吗?
【问题讨论】:
标签: spring
实际上,我认为没有任何区别,但它们的工作方式有优先级。 @PostConstruct、init-method 是 BeanPostProcessor。
@PostConstruct 是 JSR-250 注释,而 init-method 是 Spring 的初始化方法。@PostConstruct 方法,它将在调用初始化方法之前首先被调用。afterPropertiesSet,则首先调用 @PostConstruct,然后调用 afterPropertiesSet,然后再调用 init-method。有关更多信息,您可以查看 Spring 的reference documentation。
在 JSR 250 规范之前,在 xml 中使用 init-method 是首选方式,因为它将 java 类(bean)与任何 spring 特定类/注释分离。因此,如果您正在构建一个不需要依赖的库spring 基础设施 bean 则首选使用 init-method。在创建方法期间,您可以指定需要调用的方法作为初始化方法。
现在随着 Java EE 中 JSR 250 规范的引入和 spring 对这些注解的支持,在一定程度上减少了对 spring 框架的依赖。
但我不得不承认,添加这些东西会增加代码的可读性。所以这两种方法各有利弊。
【讨论】:
完整代码在这里:https://github.com/wkaczurba/so8519187 (spring-boot)
使用注释:
@Slf4j
@Component
public class MyComponent implements InitializingBean {
@Value("${mycomponent.value:Magic}")
public String value;
public MyComponent() {
log.info("MyComponent in constructor: [{}]", value); // (0) displays: Null
}
@PostConstruct
public void postConstruct() {
log.info("MyComponent in postConstruct: [{}]", value); // (1) displays: Magic
}
@Override // init-method; overrides InitializingBean.afterPropertiesSet()
public void afterPropertiesSet() {
log.info("MyComponent in afterPropertiesSet: [{}]", value); // (2) displays: Magic
}
@PreDestroy
public void preDestroy() {
log.info("MyComponent in preDestroy: [{}]", value); // (3) displays: Magic
}
}
得到我们:
正在刷新 org.springframework.context...
构造函数中的 MyComponent:[null]
postConstruct 中的 MyComponent:[Magic]
afterPropertiesSet 中的 MyComponent:[Magic]
...
在启动时为 JMX 公开注册 bean
0.561 秒内启动 DemoApplication(JVM 运行 1.011)
正在关闭 org.springframework.context... 在关闭时取消注册 JMX 公开的 bean
...
preDestroy 中的 MyComponent:[Magic]
【讨论】:
没有真正的区别。这取决于您喜欢如何配置系统,这是个人选择的问题。我自己,我更喜欢为我自己的代码使用@PostConstruct 注释(因为只有在调用方法后才正确配置 bean)并且我在从非 Spring 感知库实例化 bean 时使用init-method(不能应用注释那里,当然!)但我完全可以理解人们想要以一种或另一种方式做到这一点。
【讨论】:
@postconstruct 不是弹簧的一部分。它是 javax 包的一部分。两者都是一样的。使用 init-method 我们需要在 xml 文件中添加。如果您使用 @postconstruct,则不需要在 xml 中添加。看看下面的文章。
【讨论】:
@PostConstruct 和 init-method 之间可能存在差异,因为 @PostConstruct 在 bean 初始化(AbstractAutowireCapableBeanFactory.initializeBean() 方法)的 postProcessAfterInitialization 阶段由 CommonAnnotationBeanPostProcessor 处理,而 @ 987654327@ 方法在postProcessBeforeInitialization 阶段完成后被调用(就此而言,在postProcessAfterInitialization 阶段开始之前)。
编辑:
所以,顺序是:
1)postProcessBeforeInitialization阶段,
2) init 方法被调用,
3)postProcessAfterInitialization阶段,调用@PostConstruct方法
(作为旁注,来自已接受答案的声明
@PostConstruct,init-method 是 BeanPostProcessors
不太正确:@PostConstruct 由 BeanPostProcessor 处理,init 方法不是。)
如果某些(可能是自定义的)BeanPostProcessor(配置为(Ordered.getOrder())在CommonAnnotationBeanPostProcessor 之后执行)在其postProcessBeforeInitialization 中做一些严肃的事情,会有差异方法。
与BeanPostProcessors的默认Spring配置没有任何区别,因为所有配置为在CommonAnnotationBeanPostProcessor之后执行的BeanPostProcessors,在postProcessBeforeInitialization方法中不做任何事情。
总之,公认的答案和类似的答案都是对的……在99%的情况下,这篇文章只是为了致敬“细节中的魔鬼”这个概念
【讨论】: