spring中的单例和多例模式

单例和多例模式

spring中的scope属性的值不止两个,它一共包括8个选项:

  • singleton:默认的,单例。
  • prototype:原型。每调用一次getBean()方法则获取一个新的Bean对象。或每次注入的时候都是新对象。
  • request:一个请求对应一个Bean。仅限于在WEB应用中使用
  • session:一个会话对应一个Bean。仅限于在WEB应用中使用
  • global session:portlet应用中专用的。如果在Servlet的WEB应用中使用global session的话,和session一个效果。(portlet和servlet都是规范。servlet运行在servlet容器中,例如Tomcat。portlet运行在portlet容器中。)
  • application:一个应用对应一个Bean。仅限于在WEB应用中使用。
  • websocket:一个websocket生命周期对应一个Bean。仅限于在WEB应用中使用。
  • 自定义scope:很少使用

spring创建对象的默认方式是单例模式,本文仅讨论单例singleton和多例prototype的异同;

其一,创建多个对象的异同;其二,创建对象时的异同;

单例模式

首先是单例模式,使用最简单的User案例解释说明,代码如下

spring.xml,注意scope中的"singleton"


<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.xsd">
    <bean id="userBean"  class="com.xidu.spring.damain.User" scope="singleton">
        <property name="name" value="张三"/>
        <property name="age" value="18"/>
     bean>
beans>

User.java,注意无参构造中"System.out.println(“User类无参构造启动”);"

public class User {
    private String name;
    private int age;
    public User() {
        System.out.println("User类无参构造启动");
    }
    public User(String name, int age) {
        this.name = name;
        this.age = age;
    }
    @Override
    public String toString() {
        return "User{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public int getAge() {
        return age;
    }
    public void setAge(int age) {
        this.age = age;
    }
}

测试程序

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class SpringTest {
    public static void main(String[] args) {
        ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring.xml");
        User userBean = applicationContext.getBean("userBean", User.class);
        System.out.println(userBean.toString()+"    userBean哈希值:"+userBean.hashCode());
        userBean = applicationContext.getBean("userBean", User.class);
        System.out.println(userBean.toString()+"    userBean哈希值:"+userBean.hashCode());
    }
}

输出结果

User类无参构造启动
User{name='张三', age=18}    userBean哈希值:143110009
User{name='张三', age=18}    userBean哈希值:143110009

由结果可知,从spring中获取bean对象,启动User无参构造一次,两次获取的对象为同一个对象。

多例模式

修改spring.xml文件,注意scope中值为"prototype";

<bean id="userBean"  class="com.xidu.spring.damain.User" scope="prototype">
    <property name="name" value="张三"/>
    <property name="age" value="18"/>
 bean>

运行结果

User类无参构造启动
User{name='张三', age=18}    userBean哈希值:1881561036
User类无参构造启动
User{name='张三', age=18}    userBean哈希值:1785507932

由结果可知,程序两次调用User的无参构造,创建两个不同user对象,尽管他们的属性一致;

进一步探索

将springTest.java修改如下

public class SpringTest {
    public static void main(String[] args) {
        ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring.xml");
        System.out.println("springTest测试程序已经运行");      
//        User userBean = applicationContext.getBean("userBean", User.class);
//        System.out.println(userBean.toString()+"    userBean哈希值:"+userBean.hashCode());
//        userBean = applicationContext.getBean("userBean", User.class);
//        System.out.println(userBean.toString()+"    userBean哈希值:"+userBean.hashCode());
    }
}

首先是单例模式,运行结果

User类无参构造启动
springTest测试程序已经运行

然后是多例模式,运行结果

springTest测试程序已经运行

以上结果证明,单例模式在测试程序中获取对象时,已经提前在spring容器中创建了User对象,取出来的对象都是该对象;多例模式则没有提前在spring容器中创建该对象。

结论

1、单例模式每次从容器中获得的对象都是同一个对象;多例对象从容器中每次获取的对象都不是同一个对象;

2、单例对象在容器启动时在容器中已经创建了对象;多例对象没有体检在容器中创建对象,获取时才新建对象,这也和下面章节的解决循环依赖息息相关;

你可能感兴趣的:(spring,java,单例模式)