单例模式:每个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 D:\Java\jdk1.8.0_201\bin\java.exe "-javaagent:D:\JetBrains\IntelliJ IDEA 2018.3.5\lib\idea_rt.jar=18259:D:\JetBrains\IntelliJ IDEA 2018.3.5\bin" -Dfile.encoding=UTF-8 -classpath D:\Java\jdk1.8.0_201\jre\lib\charsets.jar;D:\Java\jdk1.8.0_201\jre\lib\deploy.jar;D:\Java\jdk1.8.0_201\jre\lib\ext\access-bridge-64.jar;D:\Java\jdk1.8.0_201\jre\lib\ext\cldrdata.jar;D:\Java\jdk1.8.0_201\jre\lib\ext\dnsns.jar;D:\Java\jdk1.8.0_201\jre\lib\ext\jaccess.jar;D:\Java\jdk1.8.0_201\jre\lib\ext\jfxrt.jar;D:\Java\jdk1.8.0_201\jre\lib\ext\localedata.jar;D:\Java\jdk1.8.0_201\jre\lib\ext\nashorn.jar;D:\Java\jdk1.8.0_201\jre\lib\ext\sunec.jar;D:\Java\jdk1.8.0_201\jre\lib\ext\sunjce_provider.jar;D:\Java\jdk1.8.0_201\jre\lib\ext\sunmscapi.jar;D:\Java\jdk1.8.0_201\jre\lib\ext\sunpkcs11.jar;D:\Java\jdk1.8.0_201\jre\lib\ext\zipfs.jar;D:\Java\jdk1.8.0_201\jre\lib\javaws.jar;D:\Java\jdk1.8.0_201\jre\lib\jce.jar;D:\Java\jdk1.8.0_201\jre\lib\jfr.jar;D:\Java\jdk1.8.0_201\jre\lib\jfxswt.jar;D:\Java\jdk1.8.0_201\jre\lib\jsse.jar;D:\Java\jdk1.8.0_201\jre\lib\management-agent.jar;D:\Java\jdk1.8.0_201\jre\lib\plugin.jar;D:\Java\jdk1.8.0_201\jre\lib\resources.jar;D:\Java\jdk1.8.0_201\jre\lib\rt.jar;D:\Temp\out\production\Temp;D:\Temp\web\WEB-INF\lib\log4j-1.2.17.jar;D:\Temp\web\WEB-INF\lib\slf4j-api-1.7.22.jar;D:\Temp\web\WEB-INF\lib\slf4j-log4j12-1.7.22.jar;D:\Temp\web\WEB-INF\lib\spring-aop-5.2.1.RELEASE.jar;D:\Temp\web\WEB-INF\lib\spring-jcl-5.2.1.RELEASE.jar;D:\Temp\web\WEB-INF\lib\spring-web-5.2.1.RELEASE.jar;D:\Temp\web\WEB-INF\lib\spring-core-5.2.1.RELEASE.jar;D:\Temp\web\WEB-INF\lib\spring-beans-5.2.1.RELEASE.jar;D:\Temp\web\WEB-INF\lib\spring-webmvc-5.2.1.RELEASE.jar;D:\Temp\web\WEB-INF\lib\spring-context-5.2.1.RELEASE.jar;D:\Temp\web\WEB-INF\lib\spring-expression-5.2.1.RELEASE.jar top.bigking.test.BigKingTest 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 D:\Java\jdk1.8.0_201\bin\java.exe "-javaagent:D:\JetBrains\IntelliJ IDEA 2018.3.5\lib\idea_rt.jar=18347:D:\JetBrains\IntelliJ IDEA 2018.3.5\bin" -Dfile.encoding=UTF-8 -classpath D:\Java\jdk1.8.0_201\jre\lib\charsets.jar;D:\Java\jdk1.8.0_201\jre\lib\deploy.jar;D:\Java\jdk1.8.0_201\jre\lib\ext\access-bridge-64.jar;D:\Java\jdk1.8.0_201\jre\lib\ext\cldrdata.jar;D:\Java\jdk1.8.0_201\jre\lib\ext\dnsns.jar;D:\Java\jdk1.8.0_201\jre\lib\ext\jaccess.jar;D:\Java\jdk1.8.0_201\jre\lib\ext\jfxrt.jar;D:\Java\jdk1.8.0_201\jre\lib\ext\localedata.jar;D:\Java\jdk1.8.0_201\jre\lib\ext\nashorn.jar;D:\Java\jdk1.8.0_201\jre\lib\ext\sunec.jar;D:\Java\jdk1.8.0_201\jre\lib\ext\sunjce_provider.jar;D:\Java\jdk1.8.0_201\jre\lib\ext\sunmscapi.jar;D:\Java\jdk1.8.0_201\jre\lib\ext\sunpkcs11.jar;D:\Java\jdk1.8.0_201\jre\lib\ext\zipfs.jar;D:\Java\jdk1.8.0_201\jre\lib\javaws.jar;D:\Java\jdk1.8.0_201\jre\lib\jce.jar;D:\Java\jdk1.8.0_201\jre\lib\jfr.jar;D:\Java\jdk1.8.0_201\jre\lib\jfxswt.jar;D:\Java\jdk1.8.0_201\jre\lib\jsse.jar;D:\Java\jdk1.8.0_201\jre\lib\management-agent.jar;D:\Java\jdk1.8.0_201\jre\lib\plugin.jar;D:\Java\jdk1.8.0_201\jre\lib\resources.jar;D:\Java\jdk1.8.0_201\jre\lib\rt.jar;D:\Temp\out\production\Temp;D:\Temp\web\WEB-INF\lib\log4j-1.2.17.jar;D:\Temp\web\WEB-INF\lib\slf4j-api-1.7.22.jar;D:\Temp\web\WEB-INF\lib\slf4j-log4j12-1.7.22.jar;D:\Temp\web\WEB-INF\lib\spring-aop-5.2.1.RELEASE.jar;D:\Temp\web\WEB-INF\lib\spring-jcl-5.2.1.RELEASE.jar;D:\Temp\web\WEB-INF\lib\spring-web-5.2.1.RELEASE.jar;D:\Temp\web\WEB-INF\lib\spring-core-5.2.1.RELEASE.jar;D:\Temp\web\WEB-INF\lib\spring-beans-5.2.1.RELEASE.jar;D:\Temp\web\WEB-INF\lib\spring-webmvc-5.2.1.RELEASE.jar;D:\Temp\web\WEB-INF\lib\spring-context-5.2.1.RELEASE.jar;D:\Temp\web\WEB-INF\lib\spring-expression-5.2.1.RELEASE.jar top.bigking.test.BigKingTest 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被创建了出来
这样就证明了懒汉模式:在第一个请求时才生成一个实例,以后的请求都调用这个实例