有状态会话bean :每个用户有自己特有的一个实例,在用户的生存期内,bean保持了用户的信息,即“有状态”;一旦用户灭亡(调用结束或实例结束),bean的生命期也告结束。即每个用户最初都会得到一个初始的bean。
无状态会话bean :bean一旦实例化就被加进会话池中,各个用户都可以共用。即使用户已经消亡,bean 的生命期也不一定结束,它可能依然存在于会话池中,供其他用户调用。由于没有特定的用户,那么也就不能保持某一用户的状态,所以叫无状态bean。但无状态会话bean 并非没有状态,如果它有自己的属性(变量),那么这些变量就会受到所有调用它的用户的影响,这是在实际应用中必须注意的
到底用singleton 还是 prototype?
到底改用哪个scope?这决定于你所注入的对象是否包含状态。
比较适合用单例模式的就是dao/service,因为他们不包含变化的成员变量,方法调用不会改变这个对象的状态(它也没有状态可言),如下面这个类
只有一个成员变量sessionFactory,而该变量是由spring注入的,全局也只有一个,可以看成是BaseDaoImpl的一个静态变量,不存在状态变化。因此下面的类比较适合用singleton。
-
@Repository("baseDao")
-
public class BaseDaoImpl<T> implements BaseDaoI<T> {
-
private SessionFactory sessionFactory;
-
public SessionFactory getSessionFactory() {
-
return sessionFactory;
-
}
-
@Autowired
-
public void setSessionFactory(SessionFactory sessionFactory) {
-
this.sessionFactory = sessionFactory;
-
}
-
public Serializable save(T o) {
-
return sessionFactory.getCurrentSession().save(o);
-
}
-
public void delete(T o) {
-
sessionFactory.getCurrentSession().delete(o);
-
}
-
public void update(T o) {
-
sessionFactory.getCurrentSession().update(o);
-
}
-
public void saveOrUpdate(T o) {
-
sessionFactory.getCurrentSession().saveOrUpdate(o);
-
}
-
}
那什么时候用prototype呢?
看下面代码
-
public class UserAction extends BaseAction implements ModelDriven<UserDTO> {
-
private static final long serialVersionUID = 1L;
-
private UserDTO userDTO = new UserDTO();
-
private UserServiceI userService;
-
public UserDTO getModel() {
-
return userdto;
-
}
-
public UserServiceI getUserService() {
-
return userService;
-
}
-
@Autowired
-
public void setUserService(UserServiceI userService) {
-
this.userService = userService;
-
}
-
}
这里有一个成员变量比较特殊 userDTO,它是由jsp传递过来并封装成的对象,而不同请求传递的参数又不同,也因此userDTO它是一个可变的变量。当我执行了login的 action 那么userDTO中便是login的用户信息,如果执行了register的action那么userDTO中便是注册的信息。假如我声明userAction为singleton会发生什么呢。我先执行注册,注册后这个userDTO被赋值,其值包含了用户注册的username,pwd,email,birthday等信息,并且该对象不会被销毁,之后我又执行了login的action,那么在login action中得到的userDTO对象中就包含了email,birthday等信息--这是我们不希望看到的。那么下次使用userAction时便又携带了上次执行后存在的状态。因此,用完userAction后必须销毁,然后由Spring容器再生成一个新的实例。这就是为什么要用prototype而不是singleton的理由了