Spring DAO 和不可变对象
Spring DAO and immutable objects
根据不可变对象的定义 (see this question),我不太确定将 Spring DAO 的 setter 作为唯一用途是否是一种确保不变性与否。例如(数据源属性):
public class MySpringPojoDAO extends JdbcDaoSupport implements IMySpringPojoDAO {
private boolean dataSourceSet = false;
@Override
public void setDataSource(DataSource dataSource){
if (dataSourceSet) {
throw new IllegalStateException("...");
}
dataSourceSet = true;
this.dataSource = dataSource;
}
}
}
在错误的情况下,使用 Spring Framework 或 IoC 确保不变性的方法是什么?
Setter 需要多次使用,而构造函数则不然。
当涉及到Spring时,最好通过constructor设置所有需要的bean:
final DataSource dataSource;// will force this property to be set only once
@Autowired(required=true)
public MySpringPojoDAO (DataSource dataSource){
this.dataSource = dataSource;
}
其次,您可以简单地添加 required 属性,这将使您的代码更短。 Spring 将确保提供了 DataSource 的 bean。
更新:
如果您仍想使用 setter,则不需要另一个标志,只需检查 !=null 条件:
@Override
public void setDataSource(DataSource dataSource){
if (this.dataSource != null) { // has been already set
throw new IllegalStateException("...");
}
this.dataSource = dataSource;
}
不可变对象只是其状态(对象的数据)在构建后无法更改的对象。 JDK 中的不可变对象示例包括 String 和 Integer。
为了确保 MySpringPojoDAO
的可变性,首先使它成为最终的,这样它就不能被扩展,其次不要引入可以改变其内部状态的方法,比如 setter。这就是我喜欢 Spring 和 Guice 依赖注入的原因,您可以注入构造函数。
final public class MySpringPojoDAO extends JdbcDaoSupport implements IMySpringPojoDAO {
// private boolean dataSourceSet = false;
@Autowired
public MySpringPojoDAO (DataSource dataSource){
this.dataSource= dataSource
}
/* @Override
public void setDataSource(DataSource dataSource){
if (dataSourceSet) {
throw new IllegalStateException("...");
}
dataSourceSet = true;
this.dataSource = dataSource;
} */
//don't use setters you'll need synchronization!!!
}
}
不可变对象
如果一个对象在构造后其状态不能改变,则该对象被认为是不可变的。最大限度地依赖不可变对象已被广泛接受为创建简单、可靠代码的合理策略。
不可变 类 - java.lang.String, java.lang.Integer, java.lang.Byte, java.lang.Character, java.lang.Short, java.lang.Boolean, java.lang.Long, java.lang.Double, java.lang.Float ...等
类 可能/可能不是最终的但不完全符合(im)可变性的要求 - java.util.Collections、java.util.Arrays 等
恕我直言,不变性是一个很好的考虑对象 - 在定义特定的 'type'(实体 - Pojo 类型)对象时。因此,虽然没有人会阻止您创建 'MySpringPojoDAO' 不可变 - 如果您实现 'MySpringPojo' 不可变并且 DAO 是可变的,这将更有意义。 (或者可能是最终的)
阅读 -
如果你查看 JdbcDaoSupport 的实现,你会发现这个:
public abstract class JdbcDaoSupport extends DaoSupport {
private JdbcTemplate jdbcTemplate;
/**
* Set the JDBC DataSource to be used by this DAO.
*/
public final void setDataSource(DataSource dataSource) {
if (this.jdbcTemplate == null || dataSource != this.jdbcTemplate.getDataSource()) {
this.jdbcTemplate = createJdbcTemplate(dataSource);
initTemplateConfig();
}
}
/**
* Return the JDBC DataSource used by this DAO.
*/
public final DataSource getDataSource() {
return (this.jdbcTemplate != null ? this.jdbcTemplate.getDataSource() : null);
}
[...]
}
JdbcDaoSupport#setDataSource
是最终的。您不能覆盖此方法。这意味着你必须这样做:
public class MySpringPojoDAO extends JdbcDaoSupport implements IMySpringPojoDAO {
@Autowired
public MySpringPojoDAO (DataSource dataSource){
setDataSource(dataSource); // JdbcDaoSupport#setDataSource(..)
}
[...]
}
所以让 Spring 像 DataSource
一样为您处理 bean 的生命周期。
您永远不应该手动创建 MySpringPojoDAO
的实例。改用:
@Autowired
private MySpringPojoDAO _myDao;
根据不可变对象的定义 (see this question),我不太确定将 Spring DAO 的 setter 作为唯一用途是否是一种确保不变性与否。例如(数据源属性):
public class MySpringPojoDAO extends JdbcDaoSupport implements IMySpringPojoDAO {
private boolean dataSourceSet = false;
@Override
public void setDataSource(DataSource dataSource){
if (dataSourceSet) {
throw new IllegalStateException("...");
}
dataSourceSet = true;
this.dataSource = dataSource;
}
}
}
在错误的情况下,使用 Spring Framework 或 IoC 确保不变性的方法是什么?
Setter 需要多次使用,而构造函数则不然。
当涉及到Spring时,最好通过constructor设置所有需要的bean:
final DataSource dataSource;// will force this property to be set only once
@Autowired(required=true)
public MySpringPojoDAO (DataSource dataSource){
this.dataSource = dataSource;
}
其次,您可以简单地添加 required 属性,这将使您的代码更短。 Spring 将确保提供了 DataSource 的 bean。
更新: 如果您仍想使用 setter,则不需要另一个标志,只需检查 !=null 条件:
@Override
public void setDataSource(DataSource dataSource){
if (this.dataSource != null) { // has been already set
throw new IllegalStateException("...");
}
this.dataSource = dataSource;
}
不可变对象只是其状态(对象的数据)在构建后无法更改的对象。 JDK 中的不可变对象示例包括 String 和 Integer。
为了确保 MySpringPojoDAO
的可变性,首先使它成为最终的,这样它就不能被扩展,其次不要引入可以改变其内部状态的方法,比如 setter。这就是我喜欢 Spring 和 Guice 依赖注入的原因,您可以注入构造函数。
final public class MySpringPojoDAO extends JdbcDaoSupport implements IMySpringPojoDAO {
// private boolean dataSourceSet = false;
@Autowired
public MySpringPojoDAO (DataSource dataSource){
this.dataSource= dataSource
}
/* @Override
public void setDataSource(DataSource dataSource){
if (dataSourceSet) {
throw new IllegalStateException("...");
}
dataSourceSet = true;
this.dataSource = dataSource;
} */
//don't use setters you'll need synchronization!!!
}
}
不可变对象
如果一个对象在构造后其状态不能改变,则该对象被认为是不可变的。最大限度地依赖不可变对象已被广泛接受为创建简单、可靠代码的合理策略。
不可变 类 - java.lang.String, java.lang.Integer, java.lang.Byte, java.lang.Character, java.lang.Short, java.lang.Boolean, java.lang.Long, java.lang.Double, java.lang.Float ...等
类 可能/可能不是最终的但不完全符合(im)可变性的要求 - java.util.Collections、java.util.Arrays 等
恕我直言,不变性是一个很好的考虑对象 - 在定义特定的 'type'(实体 - Pojo 类型)对象时。因此,虽然没有人会阻止您创建 'MySpringPojoDAO' 不可变 - 如果您实现 'MySpringPojo' 不可变并且 DAO 是可变的,这将更有意义。 (或者可能是最终的)
阅读 -
如果你查看 JdbcDaoSupport 的实现,你会发现这个:
public abstract class JdbcDaoSupport extends DaoSupport {
private JdbcTemplate jdbcTemplate;
/**
* Set the JDBC DataSource to be used by this DAO.
*/
public final void setDataSource(DataSource dataSource) {
if (this.jdbcTemplate == null || dataSource != this.jdbcTemplate.getDataSource()) {
this.jdbcTemplate = createJdbcTemplate(dataSource);
initTemplateConfig();
}
}
/**
* Return the JDBC DataSource used by this DAO.
*/
public final DataSource getDataSource() {
return (this.jdbcTemplate != null ? this.jdbcTemplate.getDataSource() : null);
}
[...]
}
JdbcDaoSupport#setDataSource
是最终的。您不能覆盖此方法。这意味着你必须这样做:
public class MySpringPojoDAO extends JdbcDaoSupport implements IMySpringPojoDAO {
@Autowired
public MySpringPojoDAO (DataSource dataSource){
setDataSource(dataSource); // JdbcDaoSupport#setDataSource(..)
}
[...]
}
所以让 Spring 像 DataSource
一样为您处理 bean 的生命周期。
您永远不应该手动创建 MySpringPojoDAO
的实例。改用:
@Autowired
private MySpringPojoDAO _myDao;