1.SpringIoC容器创建的Bean对象在Singleton371.1默认情况下是单例的
测试一下:
package com.powernode.spring6.bean;////Bean的作用域 37public class SpringBean {}
Bean的作用域 37--> <bean id="sb" class="com.powernode.spring6.bean.SpringBean"> bean>
@Test public void testBeanScope(){ ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring-scope.xml"); SpringBean sb = applicationContext.getBean("sb", SpringBean.class); System.out.println(sb); ///我们想知道这个SpringBean是单例还是多例。 SpringBean sb2 = applicationContext.getBean("sb", SpringBean.class); System.out.println(sb2); SpringBean sb3 = applicationContext.getBean("sb", SpringBean.class); System.out.println(sb3); }
在Spring的IOC容器中,Bean对象在默认情况下是单例的。
可以看出,这一次在Spring上下文初始化时,并没有创建Bean对象。
那你可能会问:如果scope没有配置,它的默认值是什么?默认值为singleton,单例。
1.2这个对象是什么时候创建的?37可为SpringBean提供一种无参数结构方法进行测试,如下:
package com.powernode.spring6.bean;////Bean的作用域 37public class SpringBean { public SpringBean() { System.out.println(实施了SpringBean的无参结构方法”); }}
@Test public void testBeanScope(){ /** * 1. 默认情况下Spring是如何管理这个Bean的: * Bean在默认情况下是单例。(单例:singleton) * 当Spring上下文初始化时,实例化。 * 每次调用getbean()方法时,都会返回单例对象。 * */ ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring-scope.xml"); }
根据测试,在默认情况下,Bean对象的创建是在初始化Spring的上下文中完成的
2.protype37要使Spring的Bean对象以多种形式存在,可在Bean标签中指定Scope属性的值为:prototype,这样,每次执行getbean()方法时,Spring就会创建bean对象,调用几次就会创建几次。
需要在bean的配置文件中添加属性scope=”prototype"
<bean id="sb" class="com.powernode.spring6.beans.SpringBean" scope="prototype" />
@Test public void testBeanScope(){ /** * 1. 默认情况下Spring是如何管理这个Bean的: * Bean在默认情况下是单例。(单例:singleton) * 当Spring上下文初始化时,实例化。 * 每次调用getbean()方法时,都会返回单例对象。 * * 2. 将bean的scope属性设置为prototype: * bean是多例的。 * 当spring上下文初始化时,这些prototype的bean就不会初始化。 * 每次调用getbean()方法时,实例化bean对象。 * prototype翻译为:原型。 */ ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring-scope.xml"); SpringBean sb = applicationContext.getBean("sb", SpringBean.class); System.out.println(sb); ///我们想知道这个SpringBean是单例还是多例。 SpringBean sb2 = applicationContext.getBean("sb", SpringBean.class); System.out.println(sb2); SpringBean sb3 = applicationContext.getBean("sb", SpringBean.class); System.out.println(sb3); }
3.scope的其他选项,Bean作用域3.1scope属性值不止两个,共8个选项:38●singleton:默认,单例。
●prototype:原型。每次调用getbean()方法,就可以获得新的bean对象。或者每次注入都是新对象。
●request:一个请求对应一个Bean。仅限于WEB应用。
●session:一个会话对应一个Bean。仅限于WEB应用。
●globalsession:portlet应用中专用。如果在servlet的WEB应用中使用globalsesion,则与session相同。(portlet和servlet都是标准的。servlet在servlet容器中运行,如tomcat。portlet在portlet容器中运行。)
●application:一个应用对应一个Bean。仅限于WEB应用。
●websocket:一个websocket生命周期对应一个bean。仅限于WEB应用。
●自定义scope:很少使用。
3.2scope自定义scope:很少使用39接下来,让我们定制一个Scope。线程级Scope在同一线程中获得相同的Bean。跨线程是不同的对象:(以下内容作为理解)
●第一步:自定义Scope。(实现Scope接口)
○Spring内置线程范围类:org.springframework.context.support.SimpleThreadScope,可直接使用。
●第二步:在Spring容器中注册自定义Scope。
<!-- 配置我们自定义的作用域 39--> <bean class="org.springframework.beans.factory.config.CustomScopeConfigurer"> <property name="scopes"> <map> <entry key="threadScope"> <!--Spring框架内置用于Scope接口的实现类。--Spring框架内置用于Scope接口的实现类。也可以自定义。--> <bean class="org.springframework.context.support.SimpleThreadScope"/> </entry> </map> </property> </bean>
第三步:使用Scope。
编写测试程序:
///测试SpringBean是否安全 39 @Test public void testThreadScope(){ ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring-scope.xml"); SpringBean sb = applicationContext.getBean("sb", SpringBean.class); System.out.println(sb); SpringBean sb1 = applicationContext.getBean("sb", SpringBean.class); System.out.println(sb1); // 启动新的线程 new Thread(new Runnable() { @Override public void run() { SpringBean sb2 = applicationContext.getBean("sb", SpringBean.class); System.out.println(sb2); SpringBean sb3 = applicationContext.getBean("sb", SpringBean.class); System.out.println(sb3); } }).start(); }