【Spring6】| Bean的作用域

目录

一:Bean的作用域

1. singleton(单例)

2. prototype(多例)

3. 其它scope

4. 自定义scop(了解)


一:Bean的作用域

1. singleton(单例)

(1)默认情况下,Spring的IoC容器创建的Bean对象是单例的(singleton)!

在Spring上下文对象初始化的时候实例化!

SpringBean类

package com.bjpowernode.spring6.bean;

public class SpringBean {
}

spring-scop.xml配置

<?xml version="1.0" encoding="UTF-8"?>
<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="springBean" class="com.bjpowernode.spring6.bean.SpringBean"/>
</beans>

测试程序

package com.bjpowernode.spring6.test;

import com.bjpowernode.spring6.bean.SpringBean;
import org.junit.Test;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class SpringScopTest {
    @Test
    public void testScop(){
        ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring-scop.xml");
        SpringBean sb1 = applicationContext.getBean("springBean", SpringBean.class);
        System.out.println(sb1);
        // 访问同一个对象
        SpringBean sb2 = applicationContext.getBean("springBean", SpringBean.class);
        System.out.println(sb2);
    }
}

执行结果:

通过测试验证:Spring的IoC容器中,默认情况下,Bean对象是单例的!

 (2)这个对象在什么时候创建的呢?

可以为SpringBean提供一个无参数构造方法,进行测试:

SpringBean类

package com.bjpowernode.spring6.bean;

public class SpringBean {
    public SpringBean() {
        System.out.println("SpringBean的无参数构造方法执行了!");
    }
}

将测试程序中getBean()所在行代码注释掉

package com.bjpowernode.spring6.test;

import com.bjpowernode.spring6.bean.SpringBean;
import org.junit.Test;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class SpringScopTest {
    @Test
    public void testScop(){
        new ClassPathXmlApplicationContext("spring-scop.xml");
    }
}

执行结果:

通过测试得知,默认情况下,Bean对象的创建是在初始化Spring上下文的时候就完成的

调用getBean方法只是从Map集合当中取出数据!

2. prototype(多例)

(1)那么就要创建多例的怎么办呢?

如果想让Spring的Bean对象以多例的形式存在,可以bean标签中指定scope属性的值为:prototype(原型、多例)!

spring-scop.xml配置

增加了scope属性,目前来说scope属性有两个值:
第一个值:singleton 单例(默认情况下不设置就是单例的)
第二个值:prototype 原型/多例

<?xml version="1.0" encoding="UTF-8"?>
<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="springBean" class="com.bjpowernode.spring6.bean.SpringBean" scope="prototype"/>
</beans>

执行结果:

得到两次创建的内存地址就不一样了,多例!

 (2)此时是什么时候创建对象呢?

在初始化上下文对象时不会创建对象,每一次执行getBean()方法的时候创建Bean对象,调用几次则创建几次!

SpringBean类

package com.bjpowernode.spring6.bean;

public class SpringBean {
    public SpringBean() {
        System.out.println("SpringBean的无参数构造方法执行了!");
    }
}

将测试程序中getBean()所在行代码注释掉

package com.bjpowernode.spring6.test;

import com.bjpowernode.spring6.bean.SpringBean;
import org.junit.Test;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class SpringScopTest {
    @Test
    public void testScop(){
        new ClassPathXmlApplicationContext("spring-scop.xml");
    }
}

执行结果:

此时并没有执行构造方法,通过测试验证确实是调用getBean方法的时候创建对象

3. 其它scope

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:很少使用。

例如:在pom.xml文件当中引入web的框架springmvc

<!--引入web的框架,例如springmvc-->
 <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-webmvc</artifactId>
      <version>6.0.0-M2</version>
</dependency>

此时的scop值就可以使用request和session的值

4. 自定义scop(了解)

接下来自定义一个Scope,线程级别的Scope!

在同一个线程中,获取的Bean都是同一个;如果是跨线程则是不同的对象!

(1)先测试单例模式下开启多线程创建的是几个Bean对象

package com.bjpowernode.spring6.test;

import com.bjpowernode.spring6.bean.SpringBean;
import org.junit.Test;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class SpringScopTest {
    @Test
    public void testThradScop(){
        ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring-scop.xml");
        // 主线程
        SpringBean sb1 = applicationContext.getBean("springBean", SpringBean.class);
        System.out.println(sb1);
        SpringBean sb2 = applicationContext.getBean("springBean", SpringBean.class);
        System.out.println(sb2);

        // 启动一个新的线程
        new Thread(new Runnable() {
            @Override
            public void run() {
                SpringBean sb3 = applicationContext.getBean("springBean", SpringBean.class);
                System.out.println(sb3);
                SpringBean sb4 = applicationContext.getBean("springBean", SpringBean.class);
                System.out.println(sb4);
            }
        }).start();
    }
}

测试结果:单例模式,拿到的都是同一个Bean对象

 

(2)测试自定义scop

第一步:自定义Scope(实现Scope接口)

实际上spring内置了线程范围的类:org.springframework.context.support.SimpleThreadScope,可以直接用!

第二步:将自定义的Scope注册到Spring容器中

注册的时候需要用到自定义范围配置器CustomScopeConfigurer(自定义范围配置器)

 <bean class="org.springframework.beans.factory.config.CustomScopeConfigurer">
        <property name="scopes">
            <map>
                <entry key="threadScop">
                    <!--这个Scope接口的实现类使用的是Spring框架内置的,也可以自定义。-->
                    <bean class="org.springframework.context.support.SimpleThreadScope"/>
                </entry>
            </map>
        </property>
    </bean>

第三步:使用Scope

<bean id="springBean" class="com.bjpowernode.spring6.bean.SpringBean" scope="threadScop"/>

完整的spring-cope.xml配置如下:

<?xml version="1.0" encoding="UTF-8"?>
<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">
    <!--先开启自定义范围配置器CustomScopeConfigurer-->
    <bean class="org.springframework.beans.factory.config.CustomScopeConfigurer">
        <property name="scopes">
            <map>
                <entry key="threadScop">
                    <!--使用内置的线程类:SimpleThreadScope-->
                    <bean class="org.springframework.context.support.SimpleThreadScope"/>
                </entry>
            </map>
        </property>
    </bean>

    <!--使用上面自动定义的scope-->
    <bean id="springBean" class="com.bjpowernode.spring6.bean.SpringBean" scope="threadScop"/>
</beans>

第四步:执行结果

还是同样的测试代码,可以看出:

对于同一个线程访问的是同一个Bean对象;对于不同的线程访问的是不同的对象!

猜你喜欢

转载自blog.csdn.net/m0_61933976/article/details/128678872
今日推荐