spring中的单例与java中的单例
2015-12-31 16:27
465 查看
一、概述:
1、spring单例通过设置属性scope="Singleton"完成(默认),其概念和java中的单例概念一致,如在web应用中,每次请求使用的是同一个实例对象。但spring的单例仅限制在其上下文环境中,并没有限制你通过其他方式去创建此对象的其他实例。说白了是spring帮你完成模拟的单例创建,使用。2、Spring中的单例和设计模式中的单例思想是一样的,不过它不需要编程来实现单例,而是由容器来配置是否单例。即消除了程序性单例
二、传统的单例模式的实现方式
1. 最原始的实现单例模式的方法(存在线程不安全):
public class SingletonOne {private static SingletonOne instance = null;
private SingletonOne() {}
public static SingletonOne getInstance() {
if (instance == null) {
instance = new SingletonOne();
}
return instance;
}
}
但是这种方法有一个弊端,就是存在线程的不安全!
比如当两个线程同时进入if(instance == null)时,一个线程判断了当前为空,然后切换到另一个线程,这个线程也判断为空。然后切换回第一个线程,进行实例化,再切换到第二个线程,进行实例化。这样就存在了两个实例。
2. 通过关键字Synchronized强制线程同步
package com.something.singleton;public class SingletonTwo {
private static SingletonTwo instance = null;
private SingletonTwo() {}
public static synchronized SingletonTwo getInstance() {
if (instance == null) {
instance = new SingletonTwo();
}
return instance;
}
}
这样当线程进行到getInstance会同步的进行,不会有线程安全问题,但是不仅仅是实例化,每次调用也需要同步,这样就会造成很多资源的浪费。
3. 通过静态内部类进行单例
public class SingletonThree {private static class SingletonHolder{
static SingletonThree instance = new SingletonThree();
}
private SingletonThree() {}
public static SingletonThree getInstance() {
return SingletonHolder.instance;
}
}
这种方法是最推荐的一种方法,由于Java的调用机制,SingletonHolder只有在调用getInstance的时候才会加载,而内部的静态类只会被加载一次,因此又是线程安全的。
总结起来:
第一种方法,是存在线程安全问题的。
第二种方法,则消耗了一定的资源。
第三种方法,比较推荐。
三、下面通过spring的factory-method来创建单例的bean
1.applicationContext.xml配置如下:
<?xml version="1.0" encoding="UTF-8"?><beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd" default-lazy-init="false">
<bean id="Test_pojo" class="cn.wy.test_singleton.Test_pojo">
<property name="age" value="10" />
<property name="name" value="xiaoming" />
<property name="height" value="30" />
</bean>
<bean id="SingletonThree" class="cn.wy.test_singleton.SingletonThree" factory-method="getInstance">
<property name="name" value="wy_test" />
<property name="pojo" ref="Test_pojo" />
</bean>
</beans>
2.Test_pojo类如下:
package cn.wy.test_singleton;/**
* @Description: TODO
* @author wangy
* @date 2015年12月31日 下午3:52:50
*/
public class Test_pojo {
private int age = 0;
private String name = "unkown";
private int height = 0;
public int getAge() {
return age;
}
public String getName() {
return name;
}
public int getHeight() {
return height;
}
public void setAge(int age) {
this.age = age;
}
public void setName(String name) {
this.name = name;
}
public void setHeight(int height) {
this.height = height;
}
}
3.Singleton类如下:
package cn.wy.test_singleton;/**
* @Description: 单例模式3
* @author wangy
* @date 2015年12月31日 下午3:39:45
*/
public class SingletonThree {
private Test_pojo pojo = new Test_pojo();
private String name = "unkown";
private SingletonThree() {}
private static class SingletonHolder{
static SingletonThree instance = new SingletonThree();
}
public static SingletonThree getInstance() {
return SingletonHolder.instance;
}
public Test_pojo getPojo() {
return pojo;
}
public void setPojo(Test_pojo pojo) {
this.pojo = pojo;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
4.测试类:
package cn.wy.task_schedule;import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import cn.wy.test_singleton.SingletonThree;
public class Application {
public static void main(String[] args) {
String[] path= new String[] {
"classpath*:applicationContext-testSingleton.xml"
};
try {
ApplicationContext context = new ClassPathXmlApplicationContext(path);
SingletonThree singleton1 = SingletonThree.getInstance();
SingletonThree singleton2 = (SingletonThree) context.getBean("SingletonThree");
System.out.println("o1'code: " + singleton1.hashCode() + ", o2's code:" + singleton2.hashCode());
System.out.println("starting");
} catch (Exception e) {
// TODO: handle exception
}
}
}
解释:在配置文件中定义"SingletonThree"的bean时候,如果有factory-method="getInstance",则上面示例中的singleton1、singleton2是同一个对象,里面的属性均一致;如果没有factory-method="getInstance",则上面示例中的singleton1、singleton2是两个不同的对象,singleton2中的Test_pojo对象是被赋过值之后的对象,而singleton1中的Test_pojo对象是仅有初始值的对象。
相关文章推荐
- Jigsaw项目会解决Java的JAR地狱问题么?
- java写一个爬虫
- Java语言基础
- Java中数据类型转换
- 【第二章】 IoC 之 2.3 IoC的配置使用——跟我学Spring3
- eclipse debug
- Spring下设置CXF的WebService客户端超时时长
- spring为什么不能注入static变量
- [JAVA][学习笔记]关于java.util.concurrent中 Future类的一些验证
- SpringMVC的异常处理
- Spring常用属性的注入及属性编辑器
- mac上切换jdk版本
- Tip:查看一个jar文件是用什么jdk版本编译的
- java JXL操作Excel文件
- Java基于socket编程
- Java序列化与反序列化
- java9.接口的应用
- Spring MVC
- springMVC、spring、mybatis整合测试
- java.io.FileNotFoundException: [WEB-INF/spring-servlet.xml] cannot be opened because it does not exist