如何使用Spring的FactoryBean介面
在Spring容器中有兩類的Bean,一類是普通的Bean,一類是工廠Bean。這兩種Bean都是被Spring的容器進行管理的。而Spring也提供了一個介面用於擴充套件工廠Bean,我們只要實現org.springframework.beans.factory.FactoryBean
即可。
如何使用
首先我們看一下FactoryBean
介面
public interface FactoryBean<T> {
T getObject() throws Exception;
Class<?> getObjectType();
boolean isSingleton();
}
複製程式碼
這三個方法的作用分別是
getObject
:返回本工廠建立的物件例項。此例項也許是共享的,依賴於該工廠返回的是單例或者是原型。getObjectType
:返回物件型別isSingleton
:表示被工廠建立的例項是否是單例
現在讓我們開始使用,建立一個UserFactory
用來建立例項User
public class User {
private String name;
private Integer age;
-----get set 方法
}
複製程式碼
UserFactory
工廠類
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
加入到容器中
@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
建立的例項
載入順序
有時候我們需要在工廠Bean建立之後,但是getObject
方法執行之前執行一些動作,例如資源配置檢查之類的動作的話,我們可以使用@PostConstruct
註解在方法上,那麼此方法就會在執行getObject()
方法執行之前先執行。
此時我們在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中更好更便捷的建立管理一些有著複雜構造邏輯的實體類。