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

通過上述demo我們可以看到:
- 確實(shí)生成了2個(gè)對(duì)象。&userFactoryBean 獲取了UserFactoryBean對(duì)面本身;userFactoryBean 獲取了通過getObject方法返回的對(duì)象
- 這里demo里面spring.xml文件一個(gè)一個(gè)注入屬性到UserFactoryBean,若屬性特別多,UserFactoryBean內(nèi)部實(shí)現(xiàn)十分復(fù)雜,這時(shí)又該如何解決呢??getObjectd的用途之一就是在于此,我們可以把name,age,birthday寫了一個(gè)字符串在springx.xml注入到UserFactoryBean,然后在getObject方法中拆分字符串給user對(duì)象賦值。這里就達(dá)到了一個(gè)效果:當(dāng)一個(gè)類內(nèi)部特別復(fù)雜的時(shí)候,有n多屬性,n多依賴關(guān)系。想要對(duì)外提供一個(gè)簡(jiǎn)單的方式可以配置起來,具體如何封裝通過getObjectd方法內(nèi)部自己實(shí)現(xiàn)。
總結(jié)
- BeanFactory是Spring里面最底層的一個(gè)接口,提供了最簡(jiǎn)單的容器的功能,即實(shí)例化、配置和管理 Bean。
- FactoryBean也是一個(gè)接口,實(shí)現(xiàn)了3個(gè)方法,通過重寫其中的getObject()方法自定義生成bean邏輯創(chuàng)建一個(gè)新的bean,為IOC容器中Bean的實(shí)現(xiàn)提供了更加靈活的方式
- 實(shí)現(xiàn)了factorybean的bean會(huì)在IOC容器中產(chǎn)生2個(gè)bean對(duì)象,一個(gè)是getObject()方法返回的bean對(duì)象,一個(gè)是實(shí)現(xiàn)了factorybean的bean的這個(gè)對(duì)象本身。通過@Component,@Service標(biāo)注了bean名字獲取的bean是getObject方法返回的bean;獲取實(shí)現(xiàn)了factorybean的bean則是通過,& + bean的名字獲取
到此這篇關(guān)于Spring中的BeanFactory與FactoryBean區(qū)別詳解的文章就介紹到這了,更多相關(guān)BeanFactory與FactoryBean內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
詳解Spring Boot對(duì) Apache Pulsar的支持
Spring Boot通過提供spring-pulsar和spring-pulsar-reactive自動(dòng)配置支持Apache Pulsar,類路徑中這些依賴存在時(shí),Spring Boot自動(dòng)配置命令式和反應(yīng)式Pulsar組件,PulsarClient自動(dòng)注冊(cè),默認(rèn)連接本地Pulsar實(shí)例,感興趣的朋友一起看看吧2024-11-11
Java畢業(yè)設(shè)計(jì)實(shí)戰(zhàn)之在線蛋糕銷售商城的實(shí)現(xiàn)
這是一個(gè)使用了java+JSP+Springboot+maven+mysql+ThymeLeaf+FTP開發(fā)的在線蛋糕銷售商城,是一個(gè)畢業(yè)設(shè)計(jì)的實(shí)戰(zhàn)練習(xí),具有線上蛋糕商城該有的所有功能,感興趣的朋友快來看看吧2022-01-01
Java并發(fā)編程之如何優(yōu)雅關(guān)閉鉤子Shutdown Hook
這篇文章主要為大家詳細(xì)介紹了Java如何實(shí)現(xiàn)優(yōu)雅關(guān)閉鉤子Shutdown Hook,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下2025-04-04
springboot之redis cache TTL選項(xiàng)的使用
這篇文章主要介紹了springboot之redis cache TTL選項(xiàng)的使用方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-07-07
SpringBoot簡(jiǎn)單實(shí)現(xiàn)定時(shí)器過程
這篇文章主要介紹了SpringBoot簡(jiǎn)單實(shí)現(xiàn)定時(shí)器過程,對(duì)于Java后端來說肯定實(shí)現(xiàn)定時(shí)功能肯定是使用到Spring封裝好的定時(shí)調(diào)度Scheduled2023-04-04
IDEA?服務(wù)器熱部署圖文詳解(On?Update?action/On?frame?deactivation)
這篇文章主要介紹了IDEA?服務(wù)器熱部署詳解(On?Update?action/On?frame?deactivation),本文通過圖文并茂的形式給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2023-03-03

