Spring中的BeanFactory與FactoryBean區(qū)別詳解
概述
- BeanFactory是一個接口,它是spring中的一個工廠,能夠生產(chǎn)bean,獲取bean,也就是IOC容器或?qū)ο蠊S。
- FactoryBean也是一個接口,實現(xiàn)了3個方法,通過重寫其中的getObject()方法自定義生成bean邏輯創(chuàng)建一個新的bean,為IOC容器中Bean的實現(xiàn)提供了更加靈活的方式,F(xiàn)actoryBean在IOC容器的基礎上給Bean的實現(xiàn)加上了一個簡單工廠模式和裝飾模式。
- 不止Spring中,包括mybatis和HIibernate框架等大量地方用到了FactoryBean,可見其設計思想的重要性。
BeanFactory
BeanFactory是Spring里面最底層的一個接口,提供了最簡單的容器的功能,即實例化、配置和管理 Bean。
Spring中實例化容器的幾種方式:
1.類路徑下實例化容器
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(“classpath:spring.xml”); UserFactoryBean userFactoryBean = (UserFactoryBean) context.getBean(“userFactoryBean”);
2.系統(tǒng)目錄下實例化容器
ApplicationContext context = new FileSystemXmlApplicationContext(new String[]{“d:\beans.xml”});
UserFactoryBean userFactoryBean = (UserFactoryBean) context.getBean(“userFactoryBean”);3.注解的方式實例化容器
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(Appconfig.class); UserFactoryBean userFactoryBean = (UserFactoryBean) context.getBean(“userFactoryBean”);
看一下BeanFactory的方法:
- boolean containsBean(String beanName) 判斷工廠中是否包含給定名稱的bean定義,若有則返回true
- Object getBean(String) 返回給定名稱注冊的bean實例。根據(jù)bean的配置情況,如果是singleton模式將返回一個共享實例,否則將返回一個新建的實例,如果沒有找到指定bean,該方法可能會拋出異常
- Object getBean(String, Class) 返回以給定名稱注冊的bean實例,并轉(zhuǎn)換為給定class類型
- Class getType(String name) 返回給定名稱的bean的Class,如果沒有找到指定的bean實例,則排除NoSuchBeanDefinitionException異常
- boolean isSingleton(String) 判斷給定名稱的bean定義是否為單例模式
- String[] getAliases(String name) 返回給定bean名稱的所有別名
FactoryBean
FactoryBean也是一個接口,它是一個bean,一個特殊的bean。實現(xiàn)了factorybean的bean,實現(xiàn)了如下3個方法:
- T getObject() throws Exception:實際返回的bean對象
- Class<?> getObjectType():獲取返回bean對象的類型
- boolean isSingleton():判斷是否是單例
- 通過重寫其中的getObject()方法自定義生成bean邏輯創(chuàng)建一個新的bean,為IOC容器中Bean的實現(xiàn)提供了更加靈活的方式
- 實現(xiàn)了factorybean的bean會在IOC容器中產(chǎn)生2個bean對象,一個是getObject()方法返回的bean對象,一個是實現(xiàn)了factorybean的bean的這個對象本身
- 通過@Component,@Service標注了bean名字獲取的bean是getObject方法返回的bean;獲取實現(xiàn)了factorybean的bean則是通過,& + bean的名字獲取
下面我們看一個簡易demo:
1.編寫掃描配置類Appconfig,bean對象User,以及實現(xiàn)了factorybean的bean:UserFactoryBean,重寫getObject方法
@Configuration
@ComponentScan("com.demo")
@ImportResource("classpath:spring.xml")
public class Appconfig {
}public class User {
private String name;
private int age;
private String birthday;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getBirthday() {
return birthday;
}
public void setBirthday(String birthday) {
this.birthday = birthday;
}
}@Component("userFactoryBean")
public class UserFactoryBean implements FactoryBean {
private String name;
private int age;
private String birthday;
@Override
public Object getObject() {
User user = new User();
user.setName(name);
user.setBirthday(birthday);
user.setAge(age);
return user;
}
@Override
public Class<?> getObjectType() {
return User.class;
}
@Override
public boolean isSingleton() {
return false;
}
public void setName(String name) {
this.name = name;
}
public void setAge(int age) {
this.age = age;
}
public void setBirthday(String birthday) {
this.birthday = birthday;
}
public String getName() {
return name;
}
public int getAge() {
return age;
}
public String getBirthday() {
return birthday;
}2.編寫spring.xml配置文件,注入name,age,birthday屬性到userFactoryBean
<bean id="userFactoryBean" class="com.demo.UserFactoryBean">
<property name="name" value="xiaoming"></property>
<property name="age" value="18"></property>
<property name="birthday" value="1225"></property>
</bean>
3.編寫test測試類
public class Test {
@org.junit.Test
public void test1(){
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(Appconfig.class);
// 獲取UserFactoryBean對面本身
UserFactoryBean userFactoryBean = (UserFactoryBean) context.getBean("&userFactoryBean");
System.out.println("UserFactoryBean------姓名:"+userFactoryBean.getName()+";年齡:"+userFactoryBean.getAge()+";生日:"+userFactoryBean.getBirthday());
// 獲取實際返回的對象,通過getObject方法返回的對象
User user = (User) context.getBean("userFactoryBean");
System.out.println("User------姓名:"+user.getName()+";年齡:"+user.getAge()+";生日:"+user.getBirthday());
}
}看一下效果:

通過上述demo我們可以看到:
- 確實生成了2個對象。&userFactoryBean 獲取了UserFactoryBean對面本身;userFactoryBean 獲取了通過getObject方法返回的對象
- 這里demo里面spring.xml文件一個一個注入屬性到UserFactoryBean,若屬性特別多,UserFactoryBean內(nèi)部實現(xiàn)十分復雜,這時又該如何解決呢??getObjectd的用途之一就是在于此,我們可以把name,age,birthday寫了一個字符串在springx.xml注入到UserFactoryBean,然后在getObject方法中拆分字符串給user對象賦值。這里就達到了一個效果:當一個類內(nèi)部特別復雜的時候,有n多屬性,n多依賴關系。想要對外提供一個簡單的方式可以配置起來,具體如何封裝通過getObjectd方法內(nèi)部自己實現(xiàn)。
總結
- BeanFactory是Spring里面最底層的一個接口,提供了最簡單的容器的功能,即實例化、配置和管理 Bean。
- FactoryBean也是一個接口,實現(xiàn)了3個方法,通過重寫其中的getObject()方法自定義生成bean邏輯創(chuàng)建一個新的bean,為IOC容器中Bean的實現(xiàn)提供了更加靈活的方式
- 實現(xiàn)了factorybean的bean會在IOC容器中產(chǎn)生2個bean對象,一個是getObject()方法返回的bean對象,一個是實現(xiàn)了factorybean的bean的這個對象本身。通過@Component,@Service標注了bean名字獲取的bean是getObject方法返回的bean;獲取實現(xiàn)了factorybean的bean則是通過,& + bean的名字獲取
到此這篇關于Spring中的BeanFactory與FactoryBean區(qū)別詳解的文章就介紹到這了,更多相關BeanFactory與FactoryBean內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
idea debug沒有force step into的問題解決
本文主要介紹了IDEA Debug中ForceStepInto按鈕消失的問題及解決方法,文中通過圖文介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2024-10-10
詳解spring cloud config整合gitlab搭建分布式的配置中心
這篇文章主要介紹了詳解spring cloud config整合gitlab搭建分布式的配置中心,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2018-01-01
Classloader隔離技術在業(yè)務監(jiān)控中的應用詳解
這篇文章主要為大家介紹了Classloader隔離技術在業(yè)務監(jiān)控中的應用詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2022-08-08
Java PriorityQueue優(yōu)點和缺點面試精講
這篇文章主要為大家介紹了Java面試中PriorityQueue的優(yōu)點和缺點及使用注意詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2023-10-10
Idea springboot如何實現(xiàn)批量啟動微服務
這篇文章主要介紹了Idea springboot如何實現(xiàn)批量啟動微服務,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下2020-05-05

