Spring中单例模式中的饿汉和懒汉以及Spring中的多例模式
链接:https://pan.baidu.com/s/1wgxnXnGbPdK1YaZvhO7PDQ
提取码:opjr
单例模式:每个bean定义只生成一个对象实例,每次getBean请求获得的都是此实例
单例模式分为饿汉模式和懒汉模式
饿汉模式:spring singleton的缺省是饿汉模式:启动容器时(即实例化容器时),为所有spring配置文件中定义的bean都生成一个实例
懒汉模式:在第一个请求时才生成一个实例,以后的请求都调用这个实例
在网上有许多这样的概念,你也一定烦了吧,我们用代码来看清楚这个过程
为了展示过程,我们需要引入log4j的jar包,把过程打印在控制台中
BigKingTest类中的代码如下:
1 package top.bigking.test; 2 3 import org.springframework.context.ApplicationContext; 4 import org.springframework.context.support.ClassPathXmlApplicationContext; 5 import top.bigking.bean.HelloService; 6 7 public class BigKingTest { 8 public static void main(String[] args) { 9 System.out.println("开始初始化容器"); 10 ApplicationContext applicationContext = new ClassPathXmlApplicationContext("application.xml"); 11 System.out.println("初始化容器结束"); 12 HelloService helloService = (HelloService) applicationContext.getBean("helloService"); 13 HelloService helloService1 = (HelloService) applicationContext.getBean("helloService"); 14 helloService.sayHello(); 15 helloService1.sayHello(); 16 System.out.println(helloService == helloService1); 17 } 18 }
application.xml的配置如下:
1 <?xml version="1.0" encoding="UTF-8"?> 2 <beans xmlns="http://www.springframework.org/schema/beans" 3 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 4 xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> 5 <bean class="top.bigking.bean.HelloService" id="helloService" scope="singleton" /> 6 </beans>
控制台的输出如下:
1 2 开始初始化容器 3 DEBUG [main] - Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@3b95a09c 4 DEBUG [main] - Loaded 1 bean definitions from class path resource [application.xml] 5 DEBUG [main] - Creating shared instance of singleton bean 'helloService' 6 初始化容器结束 7 Hello, World 8 Hello, World 9 true 10 11 Process finished with exit code 0
可以看到,在初始化容器时,helloService的bean对象实例就已经被创建了,后面的两次getBean都无法创建新的实例,而是直接使用这个实例,所以返回了true
以上,即可证明饿汉模式:启动容器时(即实例化容器时),为所有spring配置文件中定义的bean都生成一个实例,每次getBean请求获得的都是此实例
接下来我们证明懒汉模式:
修改application.xml,添加default-lazy-init属性
1 <?xml version="1.0" encoding="UTF-8"?> 2 <beans default-lazy-init="true" xmlns="http://www.springframework.org/schema/beans" 3 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 4 xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> 5 <bean class="top.bigking.bean.HelloService" id="helloService" scope="singleton" /> 6 </beans>
运行结果如下:
1 2 开始初始化容器 3 DEBUG [main] - Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@3b95a09c 4 DEBUG [main] - Loaded 1 bean definitions from class path resource [application.xml] 5 初始化容器结束 6 DEBUG [main] - Creating shared instance of singleton bean 'helloService' 7 Hello, World 8 Hello, World 9 true 10 11 Process finished with exit code 0
很明显可以看到,在容器初始化结束后,helloService实例才随着getBean被创建了出来
这样就证明了懒汉模式:在第一个请求时才生成一个实例,以后的请求都调用这个实例
问题来了,有了单例模式,那么一定有多例模式
多例模式:任何一个实例都是新的实例,调用getBean时,就new一个新实例
应该注意的是:多例模式中,实例只会随着getBean而创建,不会随着容器初始化而创建!也就是说,多例模式只有懒汉!
默认情况下scope="singleton",那么该Bean是单例
scope="prototype",则为多例,任何一个实例都是新的实例;
1 <?xml version="1.0" encoding="UTF-8"?> 2 <beans default-lazy-init="true" xmlns="http://www.springframework.org/schema/beans" 3 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 4 xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> 5 <bean class="top.bigking.bean.HelloService" id="helloService" scope="prototype" /> 6 </beans>
运行看一下结果:
1 2 开始初始化容器 3 DEBUG [main] - Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@3b95a09c 4 DEBUG [main] - Loaded 1 bean definitions from class path resource [application.xml] 5 初始化容器结束 6 Hello, World 7 Hello, World 8 false 9 10 Process finished with exit code 0
可以看到,最后的false
也就是说,这是两个被实例化的对象,是不同的!
有人可能会问,为什么控制台中,没有打印出 对象被实例化的相关信息呢?
这是因为:多例模式的对象,不归IOC容器管理!