在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
用來建立實例User
spring
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中更好更便捷的建立管理一些有着複雜構造邏輯的實體類。