spring中的单例与java中的单例
来源:互联网 发布:淘宝全网举报假货最快 编辑:程序博客网 时间:2024/06/05 22:50
一、概述:
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/beanshttp://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对象是仅有初始值的对象。
- spring中的单例与java中的单例
- Java中的单例
- Java中的单例
- spring中的单例模式
- java中的单例模式与doublecheck
- java中的单例模式与doublecheck
- java中的单例模式
- java中的单例模式
- java中的单例模式
- java中的单例模式
- Java中的单例模式
- java中的单例模式
- java中的单例模式
- Java中的单例模式
- JAVA中的单例模式
- Java中的单例模式
- java中的单例模式
- JAVA中的单例模式
- 一文读懂机器学习,大数据/自然语言处理/算法全有了……
- XML与DataSet的相互转换
- Android RecyclerView 使用完全解析 体验艺术般的控件
- Android仿微信语音聊天
- Android性能优化典范(三)
- spring中的单例与java中的单例
- Android连续点击两次按钮启动两次Activity
- Oracle——distinct的用法(效率)
- Android进阶——字符串排序
- 2015技术博客记
- intall Extra Packages for Enterprise Linux
- Py2exe使用
- JAVA-计算器
- 乐杨俊