工廠Bean

概述

在Spring容器中有一類特殊的bean叫工廠bean,普通的bean注入容器內的方式是經過調用其無參構造器建立一個對象導入在容器中,而工廠bean會經過FactoryBean的接口的getObject()方法將對象註冊在容器中。java

public interface FactoryBean<T> {
    @Nullable
    T getObject() throws Exception;

    @Nullable
    Class<?> getObjectType();

    default boolean isSingleton() {
        return true;
    }
}
複製代碼

FactoryBean有三個方法:spring

  • getObject() //返回須要註冊的對象 ,若是爲單例,該實例會放到Spring容器中單實例緩存池中
  • getObjectType() //返回對象的類型
  • isSingleton() //是不是單例 ,非單例時每次建立都會返回一個新的bean

實現原理簡單案例

下面經過一個簡單的小案例來講明:sql

  • 接口

public interface Person {
    public void speak();
} 
複製代碼
  • 實現類

public class Woman implements Person, BeanNameAware {

    private String beanName;

    @Override
    public void speak() {
        System.out.println("woman is talking");
    }

    @Override
    public void setBeanName(String beanName) {
        this.beanName = beanName;

    }
}
複製代碼
  • 工廠bean

public class PersonFactorybean implements FactoryBean<Person> {

    private Person person;

// 返回生產的對象
    @Override
    public Person getObject() throws Exception {
       person=new Woman();
        return person;
    }

    //返回生產的類型
    @Override
    public Class<?> getObjectType() {
        return Woman.class;
    }

// 返回是否時單例
    @Override
    public boolean isSingleton() {
        return false;
    }
}
複製代碼
  • 註解配置

@Configuration
public class BeanConfig {

    @Bean
    public PersonFactorybean factorybean() {
        return new PersonFactorybean();
    }
}
複製代碼
  • 測試輸出

@RunWith(SpringRunner.class)
@SpringBootTest
public class FactorybeanApplicationTests {

    @Test
    public void contextLoads() {
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(BeanConfig.class);
        String[] names = context.getBeanDefinitionNames();
        for (String name : names) {
            System.out.println(name);
        }
        Object bean = context.getBean("factorybean");
        System.out.println(bean);
    }

}
複製代碼

最後輸出的是com.demo.factorybean.Woman@7f02251 對象。緩存

應用場景

在某些場景下,實例化的過程比較複雜,須要大量的配置信息。如在Spring+MyBatis的環境下,咱們配置一個SqlSessionFactoryBean來充當SqlSessionFactory,以下:mybatis

<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
        <property name="dataSource" ref="dataSource"></property>
        <property name="mapperLocations" value="classpath:com/cn/mapper/*.xml"></property>
</bean>
複製代碼

在不少開源框架和spring集成的時候也用到FactoryBean,Spring爲FactoryBean提供了70多個實現,好比Poxy、RMI等,足見其應用值普遍。app

相關文章
相關標籤/搜索