在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;
}
}
複製代碼
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