Spring學習--Bean的作用域

**Bean的作用域**:
    作用域:一般指的是對象或者變量之間的可見範圍。而在Spring容器中是指其創建的Bean對象相對於其他Bean對象的請求可見範圍。
        Spring提供Singleton和prototype兩種基本作用域,另外提供Request、session、global、session三種web作用域;Spring還允許用戶制定自己的作用域。
    基本的作用域
        **一:Singleton:**指Singleton作用域的Bean只會在每個S平IOC容器中存在一個實例,而且其完整生命週期完全由Spring容器管理。對於所有獲取Bean的操作Spring容器將只返回同一個Bean。

            GoF單例設計模式指“保證一個類僅有一個實例,並提供一個訪問它的全局訪問點”,介紹了兩種實現:通過在類上定義靜態屬性保持該實例和通過註冊表方式。

            **1)通過在類上定義靜態屬性保持該實例**:一般指一個Java虛擬機 ClassLoader裝載的類只有一個實例,一般通過類靜態屬性保持該實例,這樣就造成需要單例的類都需要按照單例設計模式進行編碼;Spring沒采用這種方式,因爲該方式屬於侵入式設計;
                package org.liang.test;
                /**
                 * 單例類
                 */
                public class Singleton {
                    private String name;

                    private Singleton(){};
                    public static Singleton getInstance(){
                        return new Singleton();
                    }

                    public String getName() {
                        return name;
                    }

                    public void setName(String name) {
                        this.name = name;
                    }
                }
                class TsetSingleton{
                    public static void main(String [] args){
                        Singleton singleton = Singleton.getInstance();
                        singleton.setName("關羽");
                        System.out.println(singleton.getName());
                    }
                }
            **2) 通過註冊表方式:** 首先將需要單例的實例通過唯一鍵註冊到註冊表,然後通過鍵來獲取單例,讓我們直接看實現吧,注意本註冊表實現了Spring接口“SingletonBeanRegistry”,該接口定義了操作共享的單例對象,Spring容器實現將實現此接口;所以共享單例對象通過“registerSingleton”方法註冊,通過“getSingleton”方法獲取,消除了編程方式單例,注意在實現中不考慮併發。

                package org.liang.test;

                import org.liang.entity.Persion;
                import org.springframework.context.support.ClassPathXmlApplicationContext;

                /**
                 * Created by rcc on 2018/2/2.
                 */
                public class TestScope {
                    public static void main(String [] args){
                        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("spring-config.xml");
                        Persion persion = context.getBean(Persion.class);
                        Persion persion1 = context.getBean(Persion.class);

                        System.out.println(persion == persion1);
                        System.out.println("=======================================================");
                        Persion persion2 = new Persion();
                        Persion persion3 = new Persion();
                        System.out.println(persion2 == persion3);


                        System.out.println("=======================================================");
                        System.out.println(persion);
                        System.out.println(persion1);

                        /**
                         * 返回結果:
                         *      true
                         *======================================================
                         *      false
                         *
                          * 這就很奇怪了是不是,使用容器獲得的兩個所謂的新的對象居然是同一個對象,這和我們直接new兩個對象的結果剛好相反。
                                      * 不過仔細想一想也不奇怪,既然對象是從Spring容器中獲取的,會不會是容器在對象創建的時候對對象進行了緩存呢?
                                      *
                                      *  基於這個猜想,我們將對象中的屬性打印出來:
                          *
                          *      Persion{name='doudou', nickName='zhuzhu', age=18}
                          *      Persion{name='doudou', nickName='zhuzhu', age=18}
                          *  結果居然一模一樣,返回的是同一個對象。
                                      *
                                      *  那麼這到底是什麼原因呢?
                          *      <bean id="persion" class="org.liang.entity.Persion" scope="singleton">
                                    <constructor-arg index="0" value="doudou"/>
                                    <constructor-arg name="nickName" value="zhuzhu"/>
                                    <constructor-arg type="java.lang.Integer" value="18"/>
                                </bean>
                          *  原因就是這個配置:scope="singleton"  ,表示該對象是單例的,所以容器會緩存對象,每次獲取的對象都是同一個。
                                      *  在Spring容器中如果沒指定作用域默認就是“singleton”。
                                      */



                    }
                }
        **二、prototype:即原型,**指每次向Spring容器請求獲取Bean都返回一個全新的Bean,相對於“singleton”來說就是不緩存Bean,每次都是一個根據Bean定義創建的全新Bean。

            <bean id="user" class="org.liang.entity.User" scope="prototype">
                    <property name="name" value="張三"/>
                    <property name="gender" value="男"/>
                    <property name="age" value="18"/>
                </bean>

            ========================================================================================

            User user = (User) context.getBean("user");
            User user1 = (User) context.getBean("user");
            System.out.println(user == user1);

            /**
        返回結果:
                     * =======================================================
                               false   :每次獲取的都是全新的對象
                     */
    **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時講解具體使用,大家只需要知道有這些作用域就可以了。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章