单例模式:确保某一个类只有一个实例,而且自行实例化并向整个系统提供这个实例。
- Runtime类
Runtime是个单例类,表示当前JVM的运行环境。
可以看如下测试代码
Runtime runtime1 = Runtime.getRuntime();
Runtime runtime2 = Runtime.getRuntime();
System.out.println(runtime1.equals(runtime2));
返回true,两个Runtime的实例是一个对象。所以要用Runtime的对象时,不用像上面代码定义一个Runtime runtime1对象,而是直接Runtime.getRuntime()拿来用。不管调用几次都是返回同一个实例。
- Spring中的单例
如果在JVM中定义的单例类,可能由于长时间不用而被JVM自动回收。Spring的IOC容器里面定义的bean默认是单例,并且整个生命周期是Spring在管理,不会被JVM自动回收。
例如如下定义的service类
<bean id="helloWorldService" class="com.spring.HelloWorldService"/>
在J2EE工程里面,service和dao层都交给Spring管理,并且都是单例实现,每次拿到的service和到对象都是同一个对象。
- 不适合使用单例的场景
前面说到service和dao层都是单例的,可是action呢。strusts2的action里面有成员变量,对应form表单提交的数据,所以struts2的action一定不能是单例,每次请求进的action都是不同的实例,否则在高并发下成员变量的值就会混乱。
假如将struts2的action交给spring管理,一定要加上@Scope("prototype")注释,该action不是一个单例。
@Controller
@Scope("prototype")
public class LoginAction extends BaseAction {
@Resource
private ILoginService loginService;
private String userName;
private String passWord;
}
同样的道理,Servlet在web容器中只被初始化一次,是个单例类,也就是所说的线程不安全。所以Servlet里面是没有成员变量的。