天天看点

spring学习-IOC(六)-scope作用域

scope作用域

  • scope作用域定义了spring容器中生成的bean实例的可见范围,包括如下:
    • singleton:生成唯一的bean实例,是spring里的缺省作用域,spring容器初始化时进行实例化
    • prototype:每次请求时,都会生成新的bean实例。建议:有状态的bean使用prototype,无状态使用singleton,故:spring容器初始化时,不会生成prototype实例
    • request:针对每次的http请求,spring容器会创建一个全新的实例,只在当前的http请求生效
    • session:针对某个httpsession,创建全新实例,只在当前session会话生效,不同的session之间的实例是隔离的
    • global session
  • 此外,还有自定义作用域

示例:

  • 这里只演示:singleton、prototype、自定义作用域三种
  • 首先,创建一个maven工程(参照spring学习(一)中的方式)
  • 其次:创建测试类:
package ioc3;

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

public class Fly {
    public void say() {
        System.out.println("I can fly");
    }
}

/**
 * 通过实现:org.springframework.beans.factory.config.Scope实现自定义Scope的方式
 * 实现样例,参见:org.springframework.context.support.SimpleThreadScope
 * 网上样例:https://blog.csdn.net/elim168/article/details/75581670
 */
class MyScope implements Scope {

    private Map<String, Object> beanMap = new ConcurrentHashMap<String, Object>();

    @Override
    public Object get(String name, ObjectFactory<?> objectFactory) {
        System.out.println("----------> self define myScope: " + name);
        synchronized (this) {
            if (!beanMap.containsKey(name)) {
                System.out.println("----------> do not exist: " + name);
                beanMap.put(name, objectFactory.getObject());
            }
        }
        return beanMap.get(name);
    }

    @Override
    public Object remove(String name) {
        return beanMap.remove(name);
    }

    @Override
    public void registerDestructionCallback(String name, Runnable callback) {

    }

    @Override
    public Object resolveContextualObject(String key) {
        return null;
    }

    @Override
    public String getConversationId() {
        return null;
    }
}
           
  • 其次,创建配置文件:
<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">

    <!--1 singleton模式-->
    <bean id="birdFlySingleTon" class="ioc3.Fly" scope="singleton"/>

    <!--2 prototype模式-->
    <bean id="birdFlyProtoType" class="ioc3.Fly" scope="prototype"/>

    <!--3 自定义scope模式-->
    <bean id="birdFlyMyScope" class="ioc3.Fly" scope="myScope"/>

</beans>
           
  • 创建测试方法:
class Main {
    public static void main(String[] args) {
        ClassPathXmlApplicationContext beanFactory = new ClassPathXmlApplicationContext("ioc3-scope.xml");
        // 开始注册自己的bean
        beanFactory.getBeanFactory().registerScope("myScope", new MyScope());

        System.out.println("========== 1. singleton模式 ==========");
        Fly flySingleTon1 = beanFactory.getBean("birdFlySingleTon", Fly.class);
        Fly flySingleTon2 = beanFactory.getBean("birdFlySingleTon", Fly.class);
        System.out.println("多次请求时,bean实例是一样的:flySingleTon1 == flySingleTon2 : " + (flySingleTon1 == flySingleTon2));

        System.out.println("========== 2. prototype模式 ==========");
        Fly flyProtoType1 = beanFactory.getBean("birdFlyProtoType", Fly.class);
        Fly flyProtoType2 = beanFactory.getBean("birdFlyProtoType", Fly.class);
        System.out.println("多次请求时,bean实例不一样:flyProtoType1 == flyProtoType2 : " + (flyProtoType1 == flyProtoType2));

        System.out.println("========== 3. 自定义scope ==========");
        Fly flyMyScope1 = beanFactory.getBean("birdFlyMyScope", Fly.class);
        Fly flyMyScope2 = beanFactory.getBean("birdFlyMyScope", Fly.class);
        flyMyScope1.say();
        flyMyScope2.say();
        System.out.println("多次请求时,bean实例一样(可以修改get方法变成不一样):" +
                "flyMyScope1 == flyMyScope2 : " + (flyMyScope1 == flyMyScope2));


    }
}
           
  • 输出结果:
========== 1. singleton模式 ==========
多次请求时,bean实例是一样的:flySingleTon1 == flySingleTon2 : true
========== 2. prototype模式 ==========
多次请求时,bean实例不一样:flyProtoType1 == flyProtoType2 : false
========== 3. 自定义scope ==========
----------> self define myScope: birdFlyMyScope
----------> do not exist: birdFlyMyScope
----------> self define myScope: birdFlyMyScope
I can fly
I can fly
多次请求时,bean实例一样(可以修改get方法变成不一样):flyMyScope1 == flyMyScope2 : true
           
  • 结果说明
    • 可以看到singleton确实唯一,而prototype每次都不一样
    • 自定义scope可以正常使用,并且运行