如何使用Spring的FactoryBean接口

如何使用Spring的FactoryBean接口

在Spring容器中有兩類的Bean,一類是普通的Bean,一類是工廠Bean。這兩種Bean都是被Spring的容器進行管理的。而Spring也提供了一個接口用於擴展工廠Bean,咱們只要實現org.springframework.beans.factory.FactoryBean便可。java

如何使用

首先咱們看一下FactoryBean接口git

public interface FactoryBean<T> {

	T getObject() throws Exception;

	Class<?> getObjectType();

	boolean isSingleton();

}

複製代碼

這三個方法的做用分別是github

  • getObject:返回本工廠建立的對象實例。此實例也許是共享的,依賴於該工廠返回的是單例或者是原型。
  • getObjectType:返回對象類型
  • isSingleton:表示被工廠建立的實例是不是單例

如今讓咱們開始使用,建立一個UserFactory用來建立實例Userspring

public class User {

    private String name;
    private Integer age;
-----get set 方法
}

複製代碼

UserFactory工廠類bash

public class UserFactory implements FactoryBean<User> {
    private String name;
    private Integer age;
    
    @Override
    public User getObject() throws Exception {
        return new User(name,age);
    }

    @Override
    public Class<?> getObjectType() {
        return User.class;
    }

    @Override
    public boolean isSingleton() {
        return true;
    }
}

複製代碼

添加配置類將UserFactory加入到容器中ide

@Configuration
public class FactoryBeanAppConfig {

    @Bean
    public UserFactory userFactory(){
        UserFactory userFactory = new UserFactory();
        userFactory.setAge(10);
        userFactory.setName("Grace");
        return userFactory;
    }

}

複製代碼

接下來咱們就能經過UserFactory工廠類進行建立User測試

public class BeanFactoryTest extends BaseTest{

    @Autowired
    private User user;

    @Test
    public void testBeanFactory(){
        assertEquals(new Integer(10),user.getAge());
        assertEquals("Grace",user.getName());
    }
}

複製代碼

此時咱們Debug也能看到其咱們自動注入的User類就是經過UserFactory建立的實例ui

加載順序

有時候咱們須要在工廠Bean建立以後,可是getObject方法執行以前執行一些動做,例如資源配置檢查之類的動做的話,咱們可使用@PostConstruct註解在方法上,那麼此方法就會在執行getObject()方法執行以前先執行。spa

此時咱們在UserFactory工廠類中修改以下,增長@PostConstruct註解的方法,而且增長打印日誌。日誌

public class UserFactory implements FactoryBean<User> {
    private String name;
    private Integer age;

    @Override
    public User getObject() throws Exception {
        System.out.println("getObject Begin");
        return new User(name,age);
    }

    @Override
    public Class<?> getObjectType() {
        return User.class;
    }

    @Override
    public boolean isSingleton() {
        return true;
    }

    @PostConstruct
    public void Initialize(){
        System.out.println("Initialize Begin");
    }
}

複製代碼

此時咱們運行就會發現執行順序

AbstractFactoryBean

Spring爲咱們提供了一個關於FactoryBean的抽象類AbstractFactoryBean爲咱們簡化了操做。咱們直接繼承此類就能更加方便的建立單例或者非單例的實體類了。接下來咱們就演示一下如何建立單例和非單例的類。首先先建立兩個工廠,一個工廠SingleUserFactory負責建立單例,一個工廠NonSingleUserFactory負責建立非單例

public class SingleUserFactory extends AbstractFactoryBean<User> {

    private String name;
    private Integer age;

    @Override
    public Class<?> getObjectType() {
        return User.class;
    }

    @Override
    protected User createInstance() throws Exception {
        return new User(name,age);
    }
--get set方法
}

複製代碼

NonSingleUserFactory

public class NonSingleUserFactory extends AbstractFactoryBean<User> {

    private String name;
    private Integer age;
	//設置爲非單例模式
    public NonSingleUserFactory(){
        setSingleton(false);
    }

    @Override
    public Class<?> getObjectType() {
        return User.class;
    }

    @Override
    protected User createInstance() throws Exception {
        return new User(name,age);
    }
    
---- get set方法
}

複製代碼

而且在配置文件中加入對這兩個工廠類的配置

@Bean(name = "singleUser")
    public SingleUserFactory getSingle(){
        SingleUserFactory singleUserFactory = new SingleUserFactory();
        singleUserFactory.setAge(12);
        singleUserFactory.setName("Single");
        return singleUserFactory;
    }

    @Bean(name = "nonSingleUser")
    public NonSingleUserFactory getNonSingle(){
        NonSingleUserFactory nonSingleUserFactory = new NonSingleUserFactory();
        nonSingleUserFactory.setAge(12);
        nonSingleUserFactory.setName("NonSingle");
        return nonSingleUserFactory;
    }

複製代碼

在測試類中測試以下

public class SingleBeanFactoryTest extends BaseTest{
    @Resource(name = "singleUser")
    private User user1;
    @Resource(name = "singleUser")
    private User user2;
    @Resource(name = "nonSingleUser")
    private User user3;
    @Resource(name = "nonSingleUser")
    private User user4;

    @Test
    public void testSingleBean(){
        assertTrue(user1 == user2);
        assertTrue(user3 != user4);
    }
}

複製代碼

咱們查看類的路徑就能夠知道哪些類是同樣的了

從結果中咱們能夠看到SingleUserFactory工廠類建立的都是單例的對象,而NonSingleUserFactory建立的都是非單例的對象。若是是建立單例的那麼就無需設置singleton的值,由於他是默認爲True的。

使用FactoryBean可以在Spring中更好更便捷的建立管理一些有着複雜構造邏輯的實體類。

源碼可在github中查看

相關文章
相關標籤/搜索