一直以來,很多人對於Spring中的BeanFactory和FactoryBean都是分不清楚的
BeanFactory
這個其實是所有Spring Bean的容器根介面,給Spring 的容器定義一套規範,給IOC容器提供了一套完整的規範,比如我們常用到的getBean
方法等
The root interface for accessing a Spring bean container. This is the basic client view of a bean container;
定義方法:
getBean(String name)
: Spring容器中獲取對應Bean物件的方法,如存在,則返回該物件containsBean(String name)
:Spring容器中是否存在該物件isSingleton(String name)
:通過beanName是否為單例物件isPrototype(String name)
:判斷bean物件是否為多例物件isTypeMatch(String name, ResolvableType typeToMatch)
:判斷name
值獲取出來的bean與typeToMath
是否匹配getType(String name)
:獲取Bean的Class型別getAliases(String name)
:獲取name所對應的所有的別名
主要的實現類(包括抽象類):
AbstractBeanFactory
:抽象Bean工廠,絕大部分的實現類,都是繼承於他DefaultListableBeanFactory
:Spring預設的工廠類XmlBeanFactory
:前期使用XML配置用的比較多的時候用的Bean工廠AbstractXmlApplicationContext
:抽象應用容器上下文物件ClassPathXmlApplicationContext
:XML解析上下文物件,使用者建立Bean物件我們早期寫Spring的時候用的就是他
使用方式:
- 使用
ClassPathXmlApplicationContext
讀取對應的xml檔案例項對應上下文物件
ApplicationContext context = new ClassPathXmlApplicationContext(new String[] {"applicationContext.xml"});
BeanFactory factory = (BeanFactory) context;
FactoryBean
該類是SpringIOC容器是建立Bean的一種形式,這種方式建立Bean會有加成方式,融合了簡單的工廠設計模式於裝飾器模式
* Interface to be implemented by objects used within a {@link BeanFactory} which * are themselves factories for individual objects. If a bean implements this * interface, it is used as a factory for an object to expose, not directly as a * bean instance that will be exposed itself.
有些人就要問了,我直接使用Spring預設方式建立Bean不香麼,為啥還要用FactoryBean做啥,在某些情況下,對於例項Bean物件比較複雜的情況下,使用傳統方式建立bean會比較複雜,例如(使用xml配置),這樣就出現了FactoryBean介面,可以讓使用者通過實現該介面來自定義該Bean介面的例項化過程。即包裝一層,將複雜的初始化過程包裝,讓呼叫者無需關係具體實現細節。
方法:
-
T getObject()
:返回例項 -
Class<?> getObjectType();
:返回該裝飾物件的Bean的型別 -
default boolean isSingleton()
:Bean是否為單例
常用類
ProxyFactoryBean
:Aop代理BeanGsonFactoryBean
:Gson
使用
- Spring XML方式
application.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="demo" class="cn.lonecloud.spring.example.bo.Person">
<property name="age" value="10"/>
<property name="name" value="xiaoMing"/>
</bean>
<bean id="demoFromFactory" class="cn.lonecloud.spring.example.bean.PersonFactoryBean">
<property name="initStr" value="10,init from factory"/>
</bean>
</beans>
personFactoryBean.java
package cn.lonecloud.spring.example.bean;
import cn.lonecloud.spring.example.bo.Person;
import org.springframework.beans.factory.FactoryBean;
import java.util.Objects;
/**
* TODO
*
* @author lonecloud <lonecloud@aliyun.com>
* @date 2020/8/4 23:39
* @since v1.0
*/
public class PersonFactoryBean implements FactoryBean<Person> {
/**
* 初始化Str
*/
private String initStr;
@Override
public Person getObject() throws Exception {
//這裡我需要獲取對應引數
Objects.requireNonNull(initStr);
String[] split = initStr.split(",");
Person p=new Person();
p.setAge(Integer.parseInt(split[0]));
p.setName(split[1]);
//這裡可能需要還要有其他複雜事情需要處理
return p;
}
@Override
public Class<?> getObjectType() {
return Person.class;
}
public String getInitStr() {
return initStr;
}
public void setInitStr(String initStr) {
this.initStr = initStr;
}
}
main方法
package cn.lonecloud.spring.example.factory;
import cn.lonecloud.spring.example.bo.Person;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.FactoryBean;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
/**
* BeanFactory 例子
*
* @author lonecloud <lonecloud@aliyun.com>
* @date 2020/8/4 23:32
* @since v1.0
*/
public class SpringBeanFactoryMain {
public static void main(String[] args) {
//這個是BeanFactory
BeanFactory beanFactory = new ClassPathXmlApplicationContext("application.xml");
//獲取對應的物件化
Object demo = beanFactory.getBean("demo");
System.out.println(demo instanceof Person);
System.out.println(demo);
//獲取從工廠Bean中獲取物件
Person demoFromFactory = beanFactory.getBean("demoFromFactory", Person.class);
System.out.println(demoFromFactory);
//獲取對應的personFactory
Object bean = beanFactory.getBean("&demoFromFactory");
System.out.println(bean instanceof PersonFactoryBean);
PersonFactoryBean factoryBean=(PersonFactoryBean) bean;
System.out.println("初始化引數為:"+factoryBean.getInitStr());
}
}
輸出
true
Person{name='xiaoMing', age=10}
Person{name='init from factory', age=10}
true
初始化引數為:10,init from factory
區別
- BeanFactory:負責生產和管理Bean的一個工廠介面,提供一個Spring Ioc容器規範,
- FactoryBean: 一種Bean建立的一種方式,對Bean的一種擴充套件。對於複雜的Bean物件初始化建立使用其可封裝物件的建立細節。
程式碼:GitHub地址