`
xinklabi
  • 浏览: 1586203 次
  • 性别: Icon_minigender_1
  • 来自: 吉林
文章分类
社区版块
存档分类
最新评论

Spring设计模式——单例模式(转载)

 
阅读更多

单例模式也属于创建型模式,所谓单例,顾名思义,所指的就是单个实例,也就是说要保证一个类仅有一个实例。
单例模式有以下的特点:

单例类只能有一个实例

单例类必须自己创建自己的唯一实例

单例类必须给所有其他对象提供这一实例

下面我们就来写一个简单的单例模式的例子:
Public class Singleton1{
Private static final Singleton1 instance=new Singleton1();
//私有的默认构造函数
Private Singleton1(){}
//静态工厂方法
Public static Singleton1 getInstance(){

Return instance;
}
}
大家可以看出来,在这个类被加载时,静态变量instance会被初始化,此时该类的私有构造函数被调用,这时候,单例类的唯一实例就被创建出来了

值得注意的是:由于构造函数是私有的,因此该类不能被继承

还有一种写法也可以实现单例模式:
Public class Singleton2{
Private static final Singleton2 instance=null;
//私有的默认构造函数
Public Singleton1(){}
//静态工厂方法
Public synchronized static Singleton2 getInstance(){

If(instance==null){

Instance=new Singleton2();
}

Return instance;
}
}

这种写法和第一种的区别在于:实例并没有直接实例化,而是在静态工厂方法被调用的时候才进行的,而且对静态工厂方法使用了同步化,以处理多线程并发的环境。
这两种写法还有两个非常有意思的名字:第一种称为饿汉式单例,第二种称为懒汉式单例。至于为什么起这个名字,自己好好想想吧。
饿汉式单例在自己被加载时就将自己实例化,如果从资源利用效率角度来讲,比懒汉式单例类稍差些。但是从速度和反应时间角度来讲,则比懒汉式要稍好些。

但是遗憾的是:懒汉式单例类也不能被继承。

我们克服前两种单例类不能被继承的缺点,我们可以使用另外一种特殊化的单例模式,它被称为单例注册表。
Import java.util.HashMap;
Public class RegSingleton{
Static private HashMap registry=new HashMap();
//静态块,在类被加载时自动执行
Static{

RegSingleton rs=new RegSingleton();

Registry.put(rs.getClass().getName(),rs);
}
//受保护的默认构造函数,如果为继承关系,则可以调用,克服了单例类不能为继承的缺点
Protected RegSingleton(){}
//静态工厂方法,返回此类的唯一实例
public static RegSingleton getInstance(String name){

if(name==null){

name=” RegSingleton”;
}
if(registry.get(name)==null){

try{

registry.put(name,Class.forName(name).newInstance());
}
Catch(Exception ex){ex.printStackTrace();}
}
Return (RegSingleton)registry.get(name);
}
}

下面我们来看看Spring中的单例实现,当我们试图从Spring容器中取得某个类的实例时,默认情况下,Spring会才用单例模式进行创建。
<bean id="date" class="java.util.Date"/>
<bean id="date" class="java.util.Date" scope="singleton"/> (仅为Spring2.0支持)
<bean id="date" class="java.util.Date" singleton="true"/>

以上三种创建对象的方式是完全相同的,容器都会向客户返回Date类的单例引用。那么如果我不想使用默认的单例模式,每次请求我都希望获得一个新的对象怎么办呢?很简单,将scope属性值设置为prototype(原型)就可以了

<bean id="date" class="java.util.Date" scope="prototype"/>

通过以上配置信息,Spring就会每次给客户端返回一个新的对象实例。

那么Spring对单例的底层实现,到底是饿汉式单例还是懒汉式单例呢?呵呵,都不是。Spring框架对单例的支持是采用单例注册表的方式进行实现的,源码如下:

public abstract class AbstractBeanFactory implements ConfigurableBeanFactory{

/**

* 充当了Bean实例的缓存,实现方式和单例注册表相同

*/

private final Map singletonCache=new HashMap();

 

public Object getBean(String name)throws BeansException{

return getBean(name,null,null);

}

...

public Object getBean(String name,Class requiredType,Object[] args)throws BeansException{

//对传入的Bean name稍做处理,防止传入的Bean name名有非法字符(或则做转码)

String beanName=transformedBeanName(name);

Object bean=null;

 

//手工检测单例注册表

Object sharedInstance=null;

 

//使用了代码锁定同步块,原理和同步方法相似,但是这种写法效率更高

synchronized(this.singletonCache){

sharedInstance=this.singletonCache.get(beanName);

}

if(sharedInstance!=null){

...

//返回合适的缓存Bean实例

bean=getObjectForSharedInstance(name,sharedInstance);

}else{

...

//取得Bean的定义

RootBeanDefinition mergedBeanDefinition=getMergedBeanDefinition(beanName,false);

...

//根据Bean定义判断,此判断依据通常来自于组件配置文件的单例属性开关

//<bean id="date" class="java.util.Date" scope="singleton"/>

//如果是单例,做如下处理

if(mergedBeanDefinition.isSingleton()){

synchronized(this.singletonCache){

//再次检测单例注册表

sharedInstance=this.singletonCache.get(beanName);

if(sharedInstance==null){

...

try {

//真正创建Bean实例


sharedInstance=createBean(beanName,mergedBeanDefinition,args);

//向单例注册表注册Bean实例

addSingleton(beanName,sharedInstance);


}


catch (Exception ex) {

 

...


}


finally{

 

...


}

}

}

bean=getObjectForSharedInstance(name,sharedInstance);

}

//如果是非单例,即prototpye,每次都要新创建一个Bean实例

//<bean id="date" class="java.util.Date" scope="prototype"/>

else{

bean=createBean(beanName,mergedBeanDefinition,args);

}

}

...

return bean;

}
}

以上的源码对于很多同学来说,可能感觉比较恐怖,但是学习要学会抓住要领,刚才的源码中,大家真正要记住的是Spring对bean实例的创建是采用单例注册表的方式进行实现的,而这个注册表的缓存是HashMap对象,如果配置文件中的配置信息不要求使用单例,Spring会采用新建实例的方式返回对象实例

分享到:
评论

相关推荐

    设计模式-Java语言中的应用(pdf)

    《设计模式——Java语言中的应用》是一本专为Java开发者深入理解面向对象设计而编写的经典书籍。设计模式是软件工程领域中经过实践验证的、解决常见问题的有效方案,它们代表了在特定上下文中,针对特定问题的最优...

    Spring————面试题库

    Spring框架的设计遵循了经典的设计模式,它是一个模块化的架构,允许开发者根据需要选择相应的模块进行项目集成。 使用Spring框架能够为开发者带来许多好处,例如通过依赖注入(Dependency Injection, DI)方法,...

    J2EE项目实训——UML及设计模式课件.rar

    "J2EE项目实训——UML及设计模式课件.rar"这个压缩包文件显然是针对学习J2EE开发和软件设计的学生或专业人士准备的资源。其中包含的两个源码项目——在线商城项目源程序和BBS论坛社区项目源程序,都是典型的J2EE应用...

    17丨设计模式应用:编程框架中的设计模式.pdf

    GoF(Gang of Four)的23种设计模式,如工厂模式、单例模式、观察者模式等,以及Web开发中常见的MVC(Model-View-Controller)模式,都是在框架设计中广泛应用的。这些模式有助于创建松散耦合、高度内聚的系统,从而...

    设计模式与JAVA

    《设计模式与JAVA》这本书是面向Java开发者的一本经典教程,它深入浅出地介绍了软件设计中的重要概念——设计模式。设计模式是经验丰富的软件开发人员在解决常见问题时所形成的可重用解决方案,它们是经过时间考验的...

    Spring学习笔记,精华摘要

    首先,Spring中广泛运用了两种设计模式:工厂模式和单例模式。工厂模式是一种创建型设计模式,它提供了一种创建对象的最佳方式。在Spring框架中,工厂模式体现在Spring容器(BeanFactory或ApplicationContext)中,...

    Spring 源码分析文档----自用

    ### Spring 源码分析——设计模式篇 #### 一、引言 Spring框架作为Java企业级开发领域中不可或缺的一部分,其内部集成了多种设计模式,不仅有助于提高系统的可维护性和扩展性,还能够帮助开发者更好地理解和应用...

    设计模式--Java语言版本

    《设计模式——Java语言版本》这本书深入探讨了如何在Java环境下应用这些模式。 在“设计模式--Java语言版本”中,我们可以期待学习到以下关键知识点: 1. **单例模式**:确保一个类只有一个实例,并提供一个全局...

    Java与模式

    2. **Java中的设计模式分类**:设计模式通常分为三类——创建型模式(如工厂模式、抽象工厂模式、单例模式、建造者模式和原型模式),结构型模式(如适配器模式、装饰器模式、代理模式、桥接模式、组合模式、外观...

    轻量级Java EE企业应用实战——Struts 2+Spring+Hibernate整合开发电子书1

    此外,书中可能还会涉及一些最佳实践和设计模式,如单例模式、工厂模式等,以及如何使用JUnit进行单元测试,确保代码质量。对于想要提升Java EE开发能力的程序员来说,这本书无疑是一份宝贵的资源。 总的来说,《轻...

    设计模式----工厂模式

    《设计模式——工厂模式》 在软件工程领域,设计模式是一种在特定情境下解决常见问题的模板,它为程序员提供了一种标准的解决方案。工厂模式是面向对象设计中最为人熟知的设计模式之一,属于创建型模式,其主要目标...

    软件设计模式与体系结构期末课程大作业-服装管理系统.zip

    在本课程大作业“软件设计模式与体系结构——服装管理系统”中,我们将深入探讨软件开发中的关键概念,尤其是设计模式和体系结构的应用。这个服装管理系统项目涵盖了多种设计原则和架构模式,旨在帮助学生掌握如何...

    SSM模式学习路线-----[Spring入门笔记](csdn)————程序.pdf

    【Spring入门笔记】主要介绍了Spring框架的基础知识,包括Spring的核心概念、Bean的配置与作用域、依赖注入、SpringAop和SpringJdbc,以及事务声明。以下是对这些知识点的详细说明: 1. **什么是Spring?** Spring...

    计算机专业毕业设计——Java合集(78套).zip

    1. 设计模式:学习常见的设计模式,如单例、工厂、观察者、装饰器等,提高代码可读性和复用性。 2. SOLID原则:理解SOLID原则,包括单一职责、开闭、里氏替换、接口隔离和依赖倒置,提升代码质量。 3. UML建模:学习...

    spring3.1.2源码包

    4. **单例模式**:Spring中的大多数bean默认为单例模式,确保系统中只有一个实例。 5. **策略模式**:例如,Spring的事务管理支持多种策略,如编程式事务管理、声明式事务管理等。 三、源码深度探索 1. **Bean的...

    2 工厂模式-课程内容.rar

    《工厂模式——面向对象设计模式的核心理解》 工厂模式,作为软件工程中最为常见的设计模式之一,是面向对象设计中的重要概念。工厂模式的主要目的是通过引入一个中间的工厂类来负责创建对象,从而将对象的创建过程...

Global site tag (gtag.js) - Google Analytics