美文网首页我爱编程
Spring(四):Bean的作用域

Spring(四):Bean的作用域

作者: 会点代码的大叔 | 来源:发表于2016-07-22 10:24 被阅读466次

    摘自:http://jinnianshilongnian.iteye.com/blog/1415463

    Bean的作用域

    什么是作用域呢?即“scope”,在面向对象程序设计中一般指对象或变量之间的可见范围。而在Spring容器中是指其创建的Bean对象相对于其他Bean对象的请求可见范围。

    Spring提供“singleton”和“prototype”两种基本作用域,另外提供“request”、“session”、“global session”三种web作用域;Spring还允许用户定制自己的作用域。

    基本的作用域

    singleton:

    指“singleton”作用域的Bean只会在每个Spring IoC容器中存在一个实例,而且其完整生命周期完全由Spring容器管理。对于所有获取该Bean的操作Spring容器将只返回同一个Bean。

    GoF单例设计模式指“保证一个类仅有一个实例,并提供一个访问它的全局访问点”,介绍了两种实现:通过在类上定义静态属性保持该实例和通过注册表方式。
    

    1)通过在类上定义静态属性保持该实例:

    一般指一个Java虚拟机 ClassLoader装载的类只有一个实例,一般通过类静态属性保持该实例,这样就造成需要单例的类都需要按照单例设计模式进行编码;Spring没采用这种方式,因为该方式属于侵入式设计。

    public class Singleton {  
        //1.私有化构造器  
        private Singleton() {}  
        //2.单例缓存者,惰性初始化,第一次使用时初始化  
        private static class InstanceHolder {  
            private static final Singleton INSTANCE = new Singleton();  
        }  
        //3.提供全局访问点  
        public static Singleton getInstance() {  
            return InstanceHolder.INSTANCE;  
        }  
        //4.提供一个计数器来验证一个ClassLoader一个实例  
        private int counter=0;  
    } 
    

    2)通过注册表方式:

    首先将需要单例的实例通过唯一键注册到注册表,然后通过键来获取单例,让我们直接看实现吧,注意本注册表实现了Spring接口“SingletonBeanRegistry”,该接口定义了操作共享的单例对象,Spring容器实现将实现此接口;所以共享单例对象通过“registerSingleton”方法注册,通过“getSingleton”方法获取,消除了编程方式单例。

    public class SingletonBeanRegister implements SingletonBeanRegistry {  
        //单例Bean缓存池,此处不考虑并发  
        private final Map<String, Object> BEANS = new HashMap<String, Object>();  
        public boolean containsSingleton(String beanName){  
            return BEANS.containsKey(beanName);  
        }  
        public Object getSingleton(String beanName) {  
            return BEANS.get(beanName);  
        }  
        @Override  
        public int getSingletonCount() {  
            return BEANS.size();  
        }  
        @Override  
        public String[] getSingletonNames() {  
            return BEANS.keySet().toArray(new String[0]);  
        }  
        @Override  
        public void registerSingleton(String beanName, Object bean) {  
            if(BEANS.containsKey(beanName)) {  
                throw new RuntimeException("[" + beanName + "] 已存在");  
            }  
            BEANS.put(beanName, bean);  
        }  
    }  
    

    Spring是注册表单例设计模式的实现,消除了编程式单例,而且对代码是非入侵式。

    接下来让我们看看在Spring中如何配置单例Bean吧,在Spring容器中如果没指定作用域默认就是“singleton”,配置方式通过scope属性配置,具体配置如下:

    <bean  class="cn.javass.spring.chapter3.bean.Printer" scope="singleton"/>  
    

    Spring不仅会缓存单例对象,Bean定义也是会缓存的,对于惰性初始化的对象是在首次使用时根据Bean定义创建并存放于单例缓存池。

    3-5.JPG

    prototype:

    即原型,指每次向Spring容器请求获取Bean都返回一个全新的Bean,相对于“singleton”来说就是不缓存Bean,每次都是一个根据Bean定义创建的全新Bean。

    GoF原型设计模式,指用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象。
    

    Spring中的原型和GoF中介绍的原型含义是不一样的:

    • GoF通过用原型实例指定创建对象的种类,而Spring容器用Bean定义指定创建对象的种类;
    • GoF通过拷贝这些原型创建新的对象,而Spring容器根据Bean定义创建新对象。

    其相同地方都是根据某些东西创建新东西,而且GoF原型必须显示实现克隆操作,属于侵入式,而Spring容器只需配置即可,属于非侵入式。

    只需指定<bean>标签属性“scope”属性为“prototype”即可:

    <bean class="cn.javass.spring.chapter3.bean.Printer" scope="prototype"/>
    

    Spring管理原型对象在Spring容器中存储如图3-6所示,Spring不会缓存原型对象,而是根据Bean定义每次请求返回一个全新的Bean:

    3-6.JPG

    Web应用中的作用域

    在Web应用中,我们可能需要将数据存储到request、session、global session。因此Spring提供了三种Web作用域:request、session、globalSession。

    一、request作用域:

    表示每个请求需要容器创建一个全新Bean。比如提交表单的数据必须是对每次请求新建一个Bean来保持这些表单数据,请求结束释放这些数据。

    二、session作用域:

    表示每个会话需要容器创建一个全新Bean。比如对于每个用户一般会有一个会话,该用户的用户信息需要存储到会话中,此时可以将该Bean配置为web作用域。

    三、globalSession:

    类似于session作用域,只是其用于portlet环境的web应用。如果在非portlet环境将视为session作用域。

    配置方式和基本的作用域相同,只是必须要有web环境支持,并配置相应的容器监听器或拦截器从而能应用这些作用域,我们会在集成web时讲解具体使用,大家只需要知道有这些作用域就可以了。

    相关文章

      网友评论

        本文标题:Spring(四):Bean的作用域

        本文链接:https://www.haomeiwen.com/subject/nhjvjttx.html