为什么Spring依赖注入有init-method?

时间:2012-07-08 03:59:02

标签: java spring dependency-injection

我来自.NET背景,使用Unity,Ninject,Castle Windsor等依赖注入容器。最近我开始学习使用Spring的依赖注入功能。

在学习Spring时,我已经看到可以在bean XML配置上指定'init-method'和'destroy-method'的概念。

指定'init-method'的目的似乎是在bean创建时进行任何你可能想要做的设置。这是我感到困惑的地方。为什么你需要一个单独的方法来执行设置,而不是只需使用构造函数来执行对象所需的任何设置,就像正常/良好的面向对象设计所指示的那样?

换句话说,如果一个类需要一个依赖项,那么它不应该被注入构造函数中,而知道已被调用,而该对象可能存在于一个没有的状态称它为'init-method'?

3 个答案:

答案 0 :(得分:9)

在极少数情况下需要单独的init()方法:

  • 您没有任何选择的旧版API

  • 初始化具有一些副作用,例如开始Thread,连接到som外部资源

    这实际上具有更深层次的含义:当使用基于类的代理(通过)时,基类的构造函数被调用两次(第二次是代理的,而不是来自您的类) - init()方法在最终对象上只调用一次。

  • 你不应该在构造函数中执行虚拟调用(这实际上应该被编译器禁止...)

  • 有时你必须使用setter / field injection(虽然我喜欢构造函数注入),例如当使用上述基于类的代理时

  

使用构造函数来执行对象所需的任何设置,就像正常/良好的面向对象设计一样?

这实际上并不是将所有初始化代码放在构造函数中的最佳实践。构造函数中的副作用使测试和模拟变得更加困难。而是专注于在稳定已知状态中创建对象。这样你就可以这样解耦创建管理连接池的对象并物理连接到该池。

BTW destroy()是一种没有析构函数的语言的祝福,因为它允许你感激地关闭外部资源,中断线程等。经常使用它。

答案 1 :(得分:5)

你为什么需要它?

在设置了所有bean的属性之后调用init方法。如果bean需要对属性进行一些初始化或验证,而这些属性只能在设置了所有属性后才能完成,则通常需要这样做。 (如果你试图在没有“init”回调的情况下这样做,你会发现每个属性设置器都必须检查是否已经调用了其他setter。等等。如果只能在所有属性之后进行初始化,那么即使该策略也会失败已经设定了豆类循环。)

如果bean拥有需要显式释放的资源,则需要使用destroy方法;例如文件句柄,网络套接字,数据库连接。

  

......就像正常/良好的面向对象设计一样?

任何指示init和destroy事件/方法是“错误”或“禁止”的设计方法都是不现实的,应该被忽略。事实上,面向对象的设计方法通常不会指明这一点。他们至多会说通常不需要这种东西。

此外,DI实际上在某种程度上改变了设计方法的规则......至少在初始化方面。特别是,通过外部化实例的“连接”,它以经典的OO设计方法无法预期的方式从代码中抽出很多逻辑。如果有的话,这就是说需要根据依赖注入来重新审视经典的OO方法。

答案 2 :(得分:0)

如果使用setter注入,则必须使用init方法/ InitializingBean / @ PostConstruct,以便在设置/自动装配所有属性后进行初始化。否则,您有一个构造但不依赖注入的对象。如果你正在使用构造函数注入,那么在Tomasz和Stephen指出的情况下很少需要它。