Spring的Dao Service采用单例模式+ThreadLoca模式实现线程安全
2016-08-05 10:42
405 查看
在使用Spring时,很多人可能对Spring中为什么DAO和Service对象采用单实例方式很迷惑,这些读者是这么认为的:
DAO对象必须包含一个数据库的连接Connection,而这个Connection不是线程安全的,所以每个DAO都要包含一个不同的Connection对象实例,这样一来DAO对象就不能是单实例的了。
上述观点对了一半。对的是“每个DAO都要包含一个不同的Connection对象实例”这句话,错的是“DAO对象就不能是单实例”。
其实Spring在实现Service和DAO对象时,使用了ThreadLocal这个类,这个是一切的核心! 如果你不知道什么事ThreadLocal
参考下面代码,这个是《Spring3.x企业应用开发实战中的例子》
[java] view
plain copy
print?
public class SqlConnection {
//①使用ThreadLocal保存Connection变量
privatestatic ThreadLocal <Connection>connThreadLocal = newThreadLocal<Connection>();
publicstatic Connection getConnection() {
// ②如果connThreadLocal没有本线程对应的Connection创建一个新的Connection,
// 并将其保存到线程本地变量中。
if (connThreadLocal.get() == null) {
Connection conn = getConnection();
connThreadLocal.set(conn);
return conn;
} else {
return connThreadLocal.get();
// ③直接返回线程本地变量
}
}
public voidaddTopic() {
// ④从ThreadLocal中获取线程对应的Connection
try {
Statement stat = getConnection().createStatement();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
这个是例子展示了不同线程使用TopicDao时如何使得每个线程都获得不同的Connection实例副本,同时保持TopicDao本身是单实例。
DAO对象必须包含一个数据库的连接Connection,而这个Connection不是线程安全的,所以每个DAO都要包含一个不同的Connection对象实例,这样一来DAO对象就不能是单实例的了。
上述观点对了一半。对的是“每个DAO都要包含一个不同的Connection对象实例”这句话,错的是“DAO对象就不能是单实例”。
其实Spring在实现Service和DAO对象时,使用了ThreadLocal这个类,这个是一切的核心! 如果你不知道什么事ThreadLocal
Spring使用ThreadLocal解决线程安全问题:
Spring中DAO和Service都是以单实例的bean形式存在,Spring通过ThreadLocal类将有状态的变量(例如数据库连接Connection)本地线程化,从而做到多线程状况下的安全。在一次请求响应的处理线程中, 该线程贯通展示、服务、数据持久化三层,通过ThreadLocal使得所有关联的对象引用到的都是同一个变量。参考下面代码,这个是《Spring3.x企业应用开发实战中的例子》
[java] view
plain copy
print?
public class SqlConnection {
//①使用ThreadLocal保存Connection变量
privatestatic ThreadLocal <Connection>connThreadLocal = newThreadLocal<Connection>();
publicstatic Connection getConnection() {
// ②如果connThreadLocal没有本线程对应的Connection创建一个新的Connection,
// 并将其保存到线程本地变量中。
if (connThreadLocal.get() == null) {
Connection conn = getConnection();
connThreadLocal.set(conn);
return conn;
} else {
return connThreadLocal.get();
// ③直接返回线程本地变量
}
}
public voidaddTopic() {
// ④从ThreadLocal中获取线程对应的Connection
try {
Statement stat = getConnection().createStatement();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
这个是例子展示了不同线程使用TopicDao时如何使得每个线程都获得不同的Connection实例副本,同时保持TopicDao本身是单实例。
相关文章推荐
- Spring的Dao Service采用单例模式+ThreadLoca模式实现线程安全
- ssh,spring 泛型注入,泛型dao和service的实现
- DAO层与Service业务逻辑层的解耦实现之Factory工厂模式
- 基于Spring、Hibernate的通用DAO层与Service层的实现
- 基于Spring、Hibernate的通用DAO层与Service层的实现
- springmvc里面,控制器,service,dao默认是单例的,spring是怎么保证线程安全的
- SSH或SHSpringMVC下采用spring的Annotation配置dao,service,controller(便于团队开发,各自修改自己的annotation)
- 基于Spring、Hibernate的通用DAO层与Service层的实现
- ssh,spring 泛型注入,泛型dao和service的实现
- 使用Spring的@Autowired 实现DAO, Service, Controller三层的注入
- 基于Spring、Hibernate的通用DAO层与Service层的实现
- 08_Spring实现action调用service,service调用dao的过程
- java spring 简单封装出自己的DAO Service实现
- spring单例,为什么service和dao确能保证线程安全
- Spring、Hibernate的通用DAO层与Service层的实现
- 使用Spring的@Autowired 实现DAO, Service, Controller三层的注入(转)
- 基于Spring、Hibernate的通用DAO层与Service层的实现
- ssh,spring 泛型注入,泛型dao和service的实现
- 基于Spring、Hibernate的通用DAO层与Service层的实现
- Spring配置事务在DAO层和SERVICE层(事务在service中的实现)