spring創建bean的幾種實例

spring創建bean的四種常用實例

  • 通過反射調用構造方法創建bean對象
  • 通過靜態工廠方法創建bean對象
  • 通過實例工廠方法創建bean對象
  • 通過FactoryBean創建bean對象

通過反射調用構造方法創建bean對象
調用類的構造方法獲取對應的bean實例,是使用最多的方式,這種方式只需要在xml bean元素中指定class屬性,spring容器內部會自動調用該類型的構造方法來創建bean對象,將其放在容器中以供使用。

語法

<bean id="bean名稱" name="bean名稱或者別名" class="bean的完整類型名稱">
    <constructor-arg index="0" value="bean的值" ref="引用的bean名稱" />
    <constructor-arg index="1" value="bean的值" ref="引用的bean名稱" />
    <constructor-arg index="2" value="bean的值" ref="引用的bean名稱" />
    ....
    <constructor-arg index="n" value="bean的值" ref="引用的bean名稱" />
</bean>
constructor-arg用於指定構造方法參數的值

index:構造方法中參數的位置,從0開始,依次遞增

value:指定參數的值

ref:當插入的值爲容器內其他bean的時候,這個值爲容器中對應bean的名稱

案例

@Getter
@Setter
@ToString
public class UserModel {
 
    private String name;
    private int age;
 
    public UserModel() {
        this.name = "我是通過UserModel的無參構造方法創建的!";
    }
 
    public UserModel(String name, int age) {
        this.name = name;
        this.age = age;
    }
}

beans.xml配置

<!-- 通過UserModel的默認構造方法創建UserModel對象 -->
<bean id="createBeanByConstructor1" class="com.javacode2018.lesson001.demo3.UserModel"/>
 
<!-- 通過UserModel有參構造方法創建UserModel對象 -->
<bean id="createBeanByConstructor2" class="com.javacode2018.lesson001.demo3.UserModel">
    <constructor-arg index="0" value="我是通過UserModel的有參方法構造的對象!"/>
    <constructor-arg index="1" value="30"/>
</bean>

上面這2種寫法,spring容器創建這兩個UserModel的時候,都會通過反射的方式去調用UserModel類中對應的構造函數來創建UserModel對象。

測試
以下測試類,同理

public static void main(String[] args) {
        //1.bean配置文件位置
        String beanXml = "classpath:/com/javacode2018/lesson001/demo3/beans.xml";
 
        //2.創建ClassPathXmlApplicationContext容器,給容器指定需要加載的bean配置文件
        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(beanXml);
 
        System.out.println("spring容器中所有bean如下:");
 
        //getBeanDefinitionNames用於獲取容器中所有bean的名稱
        for (String beanName : context.getBeanDefinitionNames()) {
            System.out.println(beanName + ":" + context.getBean(beanName));
        }
 
    }

通過靜態工廠方法創建bean對象

我們可以創建靜態工廠,內部提供一些靜態方法來生成所需要的對象,將這些靜態方法創建的對象交給spring以供使用

<bean id="bean名稱" name="" class="靜態工廠完整類名" factory-method="靜態工廠的方法">
    <constructor-arg index="0" value="bean的值" ref="引用的bean名稱" />
    <constructor-arg index="1" value="bean的值" ref="引用的bean名稱" />
    <constructor-arg index="2" value="bean的值" ref="引用的bean名稱" />
    ....
    <constructor-arg index="n" value="bean的值" ref="引用的bean名稱" />
</bean>
class:指定靜態工廠完整的類名

factory-method:靜態工廠中的靜態方法,返回需要的對象。

constructor-arg用於指定靜態方法參數的值,用法和上面介紹的構造方法一樣。

案例


public class UserStaticFactory {
 
    /**
     * 靜態無參方法創建UserModel
     *
     * @return
     */
    public static UserModel buildUser1() {
 
        System.out.println(UserStaticFactory.class + ".buildUser1()");
 
        UserModel userModel = new UserModel();
        userModel.setName("我是無參靜態構造方法創建的!");
        return userModel;
    }
 
    /**
     * 靜態有參方法創建UserModel
     *
     * @param name 名稱
     * @param age  年齡
     * @return
     */
    public static UserModel buildUser2(String name, int age) {
 
        System.out.println(UserStaticFactory.class + ".buildUser2()");
 
        UserModel userModel = new UserModel();
        userModel.setName(name);
        userModel.setAge(age);
        return userModel;
    }
}
<!-- 通過工廠靜態無參方法創建bean對象 -->
<bean id="createBeanByStaticFactoryMethod1" class="com.javacode2018.lesson001.demo3.UserStaticFactory"
      factory-method="buildUser1"/>
 
<!-- 通過工廠靜態有參方法創建bean對象 -->
<bean id="createBeanByStaticFactoryMethod2" class="com.javacode2018.lesson001.demo3.UserStaticFactory"
      factory-method="buildUser2">
    <constructor-arg index="0" value="通過工廠靜態有參方法創建UerModel實例對象"/>
    <constructor-arg index="1" value="30"/>
</bean>

通過實例工廠方法創建bean對象

讓spring容器去調用某些對象的某些實例方法來生成bean對象放在容器中以供使用


<bean id="bean名稱" factory-bean="需要調用的實例對象bean名稱" factory-method="bean對象中的方法">
    <constructor-arg index="0" value="bean的值" ref="引用的bean名稱" />
    <constructor-arg index="1" value="bean的值" ref="引用的bean名稱" />
    <constructor-arg index="2" value="bean的值" ref="引用的bean名稱" />
    ....
    <constructor-arg index="n" value="bean的值" ref="引用的bean名稱" />
</bean>

spring容器以factory-bean的值爲bean名稱查找對應的bean對象,然後調用該對象中factory-method屬性值指定的方法,將這個方法返回的對象作爲當前bean對象放在容器中供使用。

案例
定義一個實例工廠


public class UserFactory {
    public UserModel buildUser1() {
        System.out.println("----------------------1");
        UserModel userModel = new UserModel();
        userModel.setName("bean實例方法創建的對象!");
        return userModel;
    }
 
    public UserModel buildUser2(String name, int age) {
        System.out.println("----------------------2");
        UserModel userModel = new UserModel();
        userModel.setName(name);
        userModel.setAge(age);
        return userModel;
    }
}
<!-- 定義一個工廠實例 -->
<bean id="userFactory" class="com.javacode2018.lesson001.demo3.UserFactory"/>
<!-- 通過userFactory實例的無參user方法創建UserModel對象 -->
<bean id="createBeanByBeanMethod1" factory-bean="userFactory" factory-method="buildUser1"/>
 
<!-- 通過userFactory實例的有參user方法創建UserModel對象 -->
<bean id="createBeanByBeanMethod2" factory-bean="userFactory" factory-method="buildUser2">
    <constructor-arg index="0" value="通過bean實例有參方法創建UserModel實例對象"/>
    <constructor-arg index="1" value="30"/>
</bean>

通過FactoryBean來創建bean對象

前面我們學過了BeanFactory接口,BeanFactory是spring容器的頂層接口,而這裏要說的是FactoryBean,也是一個接口,這兩個接口很容易搞混淆,FactoryBean可以讓spring容器通過這個接口的實現來創建我們需要的bean對象。

public interface FactoryBean<T> {
 
    /**
     * 返回創建好的對象
     */
    @Nullable
    T getObject() throws Exception;
 
    /**
     * 返回需要創建的對象的類型
     */
    @Nullable
    Class<?> getObjectType();
 
    /**
    * bean是否是單例的
    **/
    default boolean isSingleton() {
        return true;
    }
 
}

接口中有3個方法,前面2個方法需要我們去實現,getObject方法內部由開發者自己去實現對象的創建,然後將創建好的對象返回給Spring容器getObjectType需要指定我們創建的bean的類型;最後一個方法isSingleton表示通過這個接口創建的對象是否是單例的,如果返回false,那麼每次從容器中獲取對象的時候都會調用這個接口的getObject() 去生成bean對象。

<bean id="bean名稱" class="FactoryBean接口實現類" />
package com.javacode2018.lesson001.demo3;
 
import org.springframework.beans.factory.FactoryBean;
import org.springframework.lang.Nullable;
 
/**
 * 公衆號:路人甲Java,工作10年的前阿里P7分享Java、算法、數據庫方面的技術乾貨!堅信用技術改變命運,讓家人過上更體面的生活!
 */
public class UserFactoryBean implements FactoryBean<UserModel> {
    int count = 1;
    @Nullable
    @Override
    public UserModel getObject() throws Exception { //@1
        UserModel userModel = new UserModel();
        userModel.setName("我是通過FactoryBean創建的第"+count+++ "對象");//@4
        return userModel;
    }
 
    @Nullable
    @Override
    public Class<?> getObjectType() {
        return UserModel.class; //@2
    }
 
    @Override
    public boolean isSingleton() { 
        return true; //@3
    }
}

@1:返回了一個創建好的UserModel對象

@2:返回對象的Class對象

@3:返回true,表示創建的對象是單例的,那麼我們每次從容器中獲取這個對象的時候都是同一個對象,false的話,每次會創建

<!-- 通過FactoryBean 創建UserModel對象 -->
<bean id="createByFactoryBean" class="com.javacode2018.lesson001.demo3.UserFactoryBean"/>

轉載
https://blog.csdn.net/likun557/article/details/104284840

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章