在SpringJavaConfig中,beanreturn类型应该是接口还是实现?
In Spring JavaConfig, should the bean return type be the interface or implementation?
当我配置通过 XML 实现 DataSource
(例如 HikariCP)的 class 时,它看起来像这样:
<bean id="dataSource" class="com.zaxxer.hikari.HikariDataSource" destroy-method="close"/>
根据 Spring Reference manual,JavaConfig 中的等效项是:
@Bean (destroyMethod = "close")
public DataSource dataSource () {
return new HikariDataSource();
}
为什么我们 return 在 JavaConfig 中设置接口类型,特别是在这种情况下,DataSource
没有 close()
方法,但是实现有(并且以某种方式Spring 确实找到了 close()
方法)?
我找不到此配置方法与使用实现类型之间应用程序行为的任何区别:
@Bean (destroyMethod = "close")
public HikariDataSource dataSource () {
return new HikariDataSource();
}
即使考虑自动装配,这也不应该成为问题,因为两种 return 类型都适用于 DataSource
实例变量。
那么 return 的正确类型是什么(如果有 'correct' ),为什么?
I couldn't find any difference in the application's behavior between
this configuration method to using the implementation's type
你说得对,不会有任何区别,因为在这两种情况下,最终 returned 的是 new HikariDataSource();
,即 HikariDataSource
class 的对象.
您的第一个案例 更具可扩展性 因为将来您可以 return DataSource
的一些其他实现而不更改 return 类型。或者您可以更新该方法以实现工厂设计模式 return DataSource
的大量实现,具体取决于情况。
So what is the correct type to return (if there is a 'correct' one),
and why?
确实没有正确的方法,这完全取决于开发人员,但 "program to interface" 总是好的设计。在你的情况下,因为你正在 returning 东西所以它不会有太大的区别,但你仍然应该使用 public DataSource dataSource ()
.
当你可以创建一个接受一些参数的方法时,程序接口特别有用,假设public void dataSource (DataSource ds)
,在这种情况下你可以传递DataSource
的任何实现,所以这是一个很好的设计因为它是可扩展的。
Read more about program to interface.
此外,我建议阅读有关 Factory design pattern 的内容,这是一个 程序接口的好例子。
您应该 return 通用实现。
这就是为什么:
首先,你是对的。如果你 return impl,你仍然可以自动装配接口。所以你可以做上面的,然后:
@Autowire Datasource ds;
但是,你不能反过来。您不能 return 数据源和自动装配 HikariDataSource。
为什么这很重要?
您不希望您的实现依赖于特定的实现。例如:
您编写了您的 Appcode,并且您的所有代码都依赖于 HikariDataSource。由于这是一个数据源,假设您实现了 400 个使用它的 daos 并使用了那个 class 的实现特定细节。现在,如果你改变那个 impl,你所有的客户都会崩溃。让事情重新运转起来你会很痛苦。每次您需要更改它时,这都会重复(请注意,数据源不会经常发生这种情况)。
现在 return 接口或基础 class 不鼓励您的客户依赖实现的具体细节。之后您将可以毫无问题地快速切换数据源。只要您实现数据源接口,一切都会继续工作。
下一步:测试。
您希望为您的测试提供不同的东西(比如说数据源)。你真的想为你的测试启动一个数据库,而内存数据库就足够了吗?
现在在您的 DAO 测试中,如果您依赖 IMPL,则无法针对通用数据源 (InMemoryDataSource) 进行测试。如果你 return 一个接口,你可以为你的测试使用不同的配置来简化你的设置。
我希望这能让 sense/helps。
干杯,
亚瑟
当我配置通过 XML 实现 DataSource
(例如 HikariCP)的 class 时,它看起来像这样:
<bean id="dataSource" class="com.zaxxer.hikari.HikariDataSource" destroy-method="close"/>
根据 Spring Reference manual,JavaConfig 中的等效项是:
@Bean (destroyMethod = "close")
public DataSource dataSource () {
return new HikariDataSource();
}
为什么我们 return 在 JavaConfig 中设置接口类型,特别是在这种情况下,DataSource
没有 close()
方法,但是实现有(并且以某种方式Spring 确实找到了 close()
方法)?
我找不到此配置方法与使用实现类型之间应用程序行为的任何区别:
@Bean (destroyMethod = "close")
public HikariDataSource dataSource () {
return new HikariDataSource();
}
即使考虑自动装配,这也不应该成为问题,因为两种 return 类型都适用于 DataSource
实例变量。
那么 return 的正确类型是什么(如果有 'correct' ),为什么?
I couldn't find any difference in the application's behavior between this configuration method to using the implementation's type
你说得对,不会有任何区别,因为在这两种情况下,最终 returned 的是 new HikariDataSource();
,即 HikariDataSource
class 的对象.
您的第一个案例 更具可扩展性 因为将来您可以 return DataSource
的一些其他实现而不更改 return 类型。或者您可以更新该方法以实现工厂设计模式 return DataSource
的大量实现,具体取决于情况。
So what is the correct type to return (if there is a 'correct' one), and why?
确实没有正确的方法,这完全取决于开发人员,但 "program to interface" 总是好的设计。在你的情况下,因为你正在 returning 东西所以它不会有太大的区别,但你仍然应该使用 public DataSource dataSource ()
.
当你可以创建一个接受一些参数的方法时,程序接口特别有用,假设public void dataSource (DataSource ds)
,在这种情况下你可以传递DataSource
的任何实现,所以这是一个很好的设计因为它是可扩展的。
Read more about program to interface.
此外,我建议阅读有关 Factory design pattern 的内容,这是一个 程序接口的好例子。
您应该 return 通用实现。
这就是为什么:
首先,你是对的。如果你 return impl,你仍然可以自动装配接口。所以你可以做上面的,然后:
@Autowire Datasource ds;
但是,你不能反过来。您不能 return 数据源和自动装配 HikariDataSource。
为什么这很重要?
您不希望您的实现依赖于特定的实现。例如:
您编写了您的 Appcode,并且您的所有代码都依赖于 HikariDataSource。由于这是一个数据源,假设您实现了 400 个使用它的 daos 并使用了那个 class 的实现特定细节。现在,如果你改变那个 impl,你所有的客户都会崩溃。让事情重新运转起来你会很痛苦。每次您需要更改它时,这都会重复(请注意,数据源不会经常发生这种情况)。
现在 return 接口或基础 class 不鼓励您的客户依赖实现的具体细节。之后您将可以毫无问题地快速切换数据源。只要您实现数据源接口,一切都会继续工作。
下一步:测试。 您希望为您的测试提供不同的东西(比如说数据源)。你真的想为你的测试启动一个数据库,而内存数据库就足够了吗? 现在在您的 DAO 测试中,如果您依赖 IMPL,则无法针对通用数据源 (InMemoryDataSource) 进行测试。如果你 return 一个接口,你可以为你的测试使用不同的配置来简化你的设置。
我希望这能让 sense/helps。
干杯,
亚瑟