Spring學(xué)習(xí)筆記:Spring Bean的實(shí)例化

本文僅供學(xué)習(xí)交流使用遂庄,侵權(quán)必刪劲赠。
不作商業(yè)用途凛澎,轉(zhuǎn)載請注明出處

Spring Bean的實(shí)例化有不同方式沫换,本文將展示Spring Bean的各種實(shí)例化方式最铁。

構(gòu)造器方式

構(gòu)造器方式實(shí)例化Bean只需在Bean的Class中定義構(gòu)造器即可冷尉,然后將對應(yīng)的Bean信息注冊到容器中网严。
以下例子通過Xml配置的方式展示

  • Bean的類定義
public class User {
    private String name;
    private Integer age;

    public User() {
    }

    public User(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }


    @Override
    public String toString() {
        return "User{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}
  • Xml配置信息
  <!--    構(gòu)造器方法實(shí)例化bean配置-->
    <bean id="user-by-constructor" class="com.kgyam.domain.User"/>

  • 啟動(dòng)類
public class BeanInstantiationDemo {
    public static void main(String[] args) {
        BeanFactory beanFactory = new ClassPathXmlApplicationContext ("classpath:META-INF/bean-instantiation-context.xml");
        User constructorUser = instantiationByConstructor (beanFactory);
}

  static User instantiationByConstructor(BeanFactory beanFactory) {
        User user = beanFactory.getBean ("user-by-constructor", User.class);
        System.out.println ("instantiationByConstructor user:" + user);
        return user;
    }

}

靜態(tài)工廠方法

靜態(tài)工廠方法就是在剛才的User類中添加一個(gè)靜態(tài)工廠方法,然后將這個(gè)方法配置到Bean的配置信息factory-method

  • User中添加一個(gè)靜態(tài)工廠方法
public class User {
    private String name;
    private Integer age;

    public User() {
    }

    public User(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }


    @Override
    public String toString() {
        return "User{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }


    public static User createUser() {
        return new User();
    }
}
  • Xml配置信息
   <!--    靜態(tài)工廠方法實(shí)例化bean配置-->
    <bean id="user-by-static-method" factory-method="createUser" class="com.kgyam.domain.User"/>

  • 啟動(dòng)類
public class BeanInstantiationDemo {
    public static void main(String[] args) {
        BeanFactory beanFactory = new ClassPathXmlApplicationContext ("classpath:META-INF/bean-instantiation-context.xml");
             User staticUser = instantiationByStaticMethod (beanFactory);
}


  static User instantiationByStaticMethod(BeanFactory beanFactory) {
        User user = beanFactory.getBean ("user-by-static-method", User.class);
        System.out.println ("instantiationByStaticMethod user:" + user);
        return user;
    }

}

Factory Method

工廠方法需要定義一個(gè)能創(chuàng)建User的工廠Bean垢村,將這個(gè)工廠Bean配置到factory-bean嘉栓。

  • UserFactory接口
public interface UserFactory {
    User createUser();
}
  • UserFactory的默認(rèn)實(shí)現(xiàn)
/**
 * User實(shí)例工廠
 */
public class DefaultUserFactory implements UserFactory {
    @Override
    public User createUser() {
        return User.createUser();
    }
}
  • Xml配置
    <bean id="user-by-factory-method" factory-bean="user-factory" class="com.kgyam.domain.User"></bean>

    <!--    工廠方法的工廠bean配置-->
    <bean id="user-factory" class="com.kgyam.factory.DefaultUserFactory"/>
  • 啟動(dòng)類跟上面的是一樣的侵佃,只是getBean的BeanName改下就好

FactoryBean

需要實(shí)現(xiàn)FactoryBean接口馋辈,并將實(shí)現(xiàn)類注冊到容器中

  • FactoryBean的實(shí)現(xiàn)類
/**
 * User的FactoryBean
 */
public class UserFactoryBean implements FactoryBean {
    @Override
    public Object getObject() throws Exception {
        return new User ();
    }

    @Override
    public Class<?> getObjectType() {
        return User.class;
    }
}
  • Xml配置
   <!--  通過factoryBean實(shí)例化user的factoryBean配置  -->
   <bean id="user-factory-bean" class="com.kgyam.domain.UserFactoryBean" />
  • 啟動(dòng)類這里迈螟,雖然bean定義的class是UserFactoryBean,但是接收返回的類型還是使用User褥民,beanName改成對應(yīng)Xml配置定義的消返。獲取Bean的方法如下
static User instantiationByFactroyBean(BeanFactory beanFactory) {
        User user = beanFactory.getBean ("user-factory-bean", User.class);
        System.out.println ("instantiationByFactroyBean user:" + user);
        return user;
    }

ServiceLoaderFactoryBean

通過ServiceLoaderFactoryBean的這種方式實(shí)例化Bean利用的是SPI機(jī)制實(shí)現(xiàn)的耘拇。

  • 接口類
public interface UserService {
    User createUser();
}

  • 接口實(shí)現(xiàn)類

這里定義兩個(gè)接口實(shí)現(xiàn)類

public class DefaultUserServiceImpl implements UserService {
    @Override
    public User createUser() {
        User user = User.createUser();
        user.setName("defaultUser");
        return user;
    }
}


public class CustomUserServiceImpl implements UserService {
    @Override
    public User createUser() {
        User user = User.createUser();
        user.setName("customUser");
        return user;
    }
}
  • META-INF下services配置
    這里注意的是配置文件名稱需要時(shí)接口的限定類名,配置文件中配置的是實(shí)現(xiàn)類的限定類名秦驯。這里屬于SPI的知識译隘,不過多闡述
com.kgyam.domain.service.DefaultUserServiceImpl
com.kgyam.domain.service.CustomUserServiceImpl
  • Xml配置
    注意這里的class配置的是ServiceLoaderFactoryBean
    <bean id="service-loader-factory-bean"         class="org.springframework.beans.factory.serviceloader.ServiceLoaderFactoryBean">
        <property name="serviceType" value="com.kgyam.domain.service.UserService"/>
    </bean>
  • 啟動(dòng)類
public class BeanInstantiationDemo {
   public static void main(String[] args) {
        ApplicationContext applicationContext = new ClassPathXmlApplicationContext("classpath:META-INF/bean-instantiation-special-context.xml");
        instantiationByServiceLoader(applicationContext);
    }
}

 /**
     * 通過ServiceLoaderFactoryBean方式實(shí)例化bean
     * <p>
     * 使用SPI的方式還是需要遵循SPI原來的規(guī)范,META-INF下設(shè)定好services的文件
     * 否則會(huì)無法找到這些實(shí)現(xiàn)類厅目。
     *
     * @param beanFactory
     */
    static void instantiationByServiceLoader(BeanFactory beanFactory) {
        ServiceLoader<UserService> services = beanFactory.getBean("service-loader-factory-bean", ServiceLoader.class);
        Iterator<UserService> iterator = services.iterator();
        while (iterator.hasNext()) {
            User user = iterator.next().createUser();
            System.out.println(user);
        }
    }

BeanDefinitionRegistry

通過BeanDefinitionRegistry注冊BeanDefinition實(shí)現(xiàn)Bean實(shí)例化

  • 啟動(dòng)類
    這里AnnotationConfigApplicationContext實(shí)現(xiàn)了BeanDefinitionRegistry,
    所以通過上下文對象注冊即可法严。
public class BeanInstantiationDemo {
   public static void main(String[] args) {
          AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext ();
        applicationContext.register (BeanInstantiationSpecialDemo.class);

        BeanDefinitionBuilder beanDefinitionBuilder = genericBeanDefinition (User.class);
        beanDefinitionBuilder.addPropertyValue ("name", "dali");
        /*
        因?yàn)锳nnotationConfigApplicationContext實(shí)現(xiàn)了BeanDefinitionRegistry接口,所以可以直接調(diào)用
         */
        applicationContext.registerBeanDefinition ("dali-user", beanDefinitionBuilder.getBeanDefinition ());
        applicationContext.refresh ();

        User user = applicationContext.getBean ("dali-user", User.class);
        System.out.println ("BeanDefinitionRegistry#registerBeanDefinition(String,Object):" + user);
        applicationContext.close ();
    }
}

參考文獻(xiàn)

Spring官方文檔

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末损敷,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子深啤,更是在濱河造成了極大的恐慌拗馒,老刑警劉巖,帶你破解...
    沈念sama閱讀 212,222評論 6 493
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件溯街,死亡現(xiàn)場離奇詭異诱桂,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)呈昔,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,455評論 3 385
  • 文/潘曉璐 我一進(jìn)店門挥等,熙熙樓的掌柜王于貴愁眉苦臉地迎上來堤尾,“玉大人哲泊,你說我怎么就攤上這事∠入” “怎么了怀薛?”我有些...
    開封第一講書人閱讀 157,720評論 0 348
  • 文/不壞的土叔 我叫張陵畦攘,是天一觀的道長。 經(jīng)常有香客問我,道長,這世上最難降的妖魔是什么象踊? 我笑而不...
    開封第一講書人閱讀 56,568評論 1 284
  • 正文 為了忘掉前任史隆,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘号显。我一直安慰自己羹应,他們只是感情好雳刺,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,696評論 6 386
  • 文/花漫 我一把揭開白布累颂。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上悦荒,一...
    開封第一講書人閱讀 49,879評論 1 290
  • 那天,我揣著相機(jī)與錄音,去河邊找鬼。 笑死媒佣,一個(gè)胖子當(dāng)著我的面吹牛也糊,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播钞馁,決...
    沈念sama閱讀 39,028評論 3 409
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了全闷?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,773評論 0 268
  • 序言:老撾萬榮一對情侶失蹤萍启,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后勘纯,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,220評論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡唐责,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,550評論 2 327
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了章母。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,697評論 1 341
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡浙巫,死狀恐怖金蜀,靈堂內(nèi)的尸體忽然破棺而出刷后,到底是詐尸還是另有隱情,我是刑警寧澤渊抄,帶...
    沈念sama閱讀 34,360評論 4 332
  • 正文 年R本政府宣布尝胆,位于F島的核電站,受9級特大地震影響护桦,放射性物質(zhì)發(fā)生泄漏含衔。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 40,002評論 3 315
  • 文/蒙蒙 一二庵、第九天 我趴在偏房一處隱蔽的房頂上張望贪染。 院中可真熱鬧,春花似錦催享、人聲如沸杭隙。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,782評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽寺渗。三九已至,卻和暖如春兰迫,著一層夾襖步出監(jiān)牢的瞬間信殊,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,010評論 1 266
  • 我被黑心中介騙來泰國打工汁果, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留涡拘,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 46,433評論 2 360
  • 正文 我出身青樓据德,卻偏偏與公主長得像鳄乏,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個(gè)殘疾皇子棘利,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,587評論 2 350

推薦閱讀更多精彩內(nèi)容