Spring中的FactoryBean與ObjectFactory詳解
FactoryBean
public interface FactoryBean<T> {
//獲取對(duì)象
T getObject() throws Exception;
//獲取對(duì)象類型
Class<?> getObjectType();
//是否單例,默認(rèn)true
default boolean isSingleton() {
return true;
}
}FactoryBean是一種特殊的bean,本身又是個(gè)工廠,實(shí)現(xiàn)了FactoryBean的bean會(huì)被注冊(cè)到容器中。
ObjectFactory
public interface ObjectFactory<T> {
//獲取對(duì)象
T getObject() throws BeansException;
}ObjectFactory就是個(gè)對(duì)象工廠。
示例對(duì)比
public class Cat {
public Cat() {
System.out.println("調(diào)用了Cat構(gòu)造器");
}
}
@Component
public class MyFactoryBean implements FactoryBean<Dog> {
@Override
public Dog getObject() throws Exception {
return new Dog();
}
@Override
public Class<?> getObjectType() {
return Dog.class;
}
@Override
public boolean isSingleton() {
return true;
}
}MyFactoryBean用來生成Dog對(duì)象。
public class Cat {
public Cat() {
System.out.println("調(diào)用了Cat構(gòu)造器");
}
}
@Component
public class MyObjectFactory implements ObjectFactory<Cat> {
@Override
public Cat getObject() throws BeansException {
return new Cat();
}
}MyObjectFactory用來生成Cat對(duì)象。
System.out.println(ctx.getBean("myFactoryBean"));
System.out.println(ctx.getBean("myFactoryBean"));
System.out.println(ctx.getBean("&myFactoryBean"));
System.out.println(((MyObjectFactory)ctx.getBean("myObjectFactory")).getObject());
//輸出:
調(diào)用了Dog構(gòu)造器
com.brain.demo.factory.Dog@58c1da09
com.brain.demo.factory.Dog@58c1da09
com.brain.demo.factory.MyFactoryBean@2b2954e1
調(diào)用了Cat構(gòu)造器
com.brain.demo.factory.Cat@58d6e55aObjectFactory沒啥說的,就是對(duì)象工廠,通過getObject獲取對(duì)象。
重點(diǎn)看下FactoryBean。MyFactoryBean本身作為bean(“myFactoryBean”)被掃描進(jìn)容器中,即singletonObjects。當(dāng)通過getBean或者@Autowired等方式需要獲得bean時(shí),調(diào)用getObject或者從緩存中獲取所需的對(duì)象。
protected <T> T doGetBean(final String name, @Nullable final Class<T> requiredType,
@Nullable final Object[] args, boolean typeCheckOnly) throws BeansException {
//名稱轉(zhuǎn)換
final String beanName = transformedBeanName(name);
Object bean;
// Eagerly check singleton cache for manually registered singletons.
Object sharedInstance = getSingleton(beanName);
//這個(gè)地方獲得到bean("myFactoryBean")
if (sharedInstance != null && args == null) {
if (logger.isTraceEnabled()) {
if (isSingletonCurrentlyInCreation(beanName)) {
logger.trace("Returning eagerly cached instance of singleton bean '" + beanName +
"' that is not fully initialized yet - a consequence of a circular reference");
}
else {
logger.trace("Returning cached instance of singleton bean '" + beanName + "'");
}
}
//這里進(jìn)行了轉(zhuǎn)換
bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
}
}protected Object getObjectForBeanInstance(
Object beanInstance, String name, String beanName, @Nullable RootBeanDefinition mbd) {
// Don't let calling code try to dereference the factory if the bean isn't a factory.
//判斷name是否是&開頭的,代表是FactoryBean
if (BeanFactoryUtils.isFactoryDereference(name)) {
if (beanInstance instanceof NullBean) {
return beanInstance;
}
if (!(beanInstance instanceof FactoryBean)) {
throw new BeanIsNotAFactoryException(beanName, beanInstance.getClass());
}
if (mbd != null) {
mbd.isFactoryBean = true;
}
return beanInstance;
}
// Now we have the bean instance, which may be a normal bean or a FactoryBean.
// If it's a FactoryBean, we use it to create a bean instance, unless the
// caller actually wants a reference to the factory.
//不是FactoryBean,就是普通的bean,返回
if (!(beanInstance instanceof FactoryBean)) {
return beanInstance;
}
Object object = null;
if (mbd != null) {
mbd.isFactoryBean = true;
}
else {
object = getCachedObjectForFactoryBean(beanName);
}
if (object == null) {
// Return bean instance from factory.
FactoryBean<?> factory = (FactoryBean<?>) beanInstance;
// Caches object obtained from FactoryBean if it is a singleton.
if (mbd == null && containsBeanDefinition(beanName)) {
mbd = getMergedLocalBeanDefinition(beanName);
}
boolean synthetic = (mbd != null && mbd.isSynthetic());
//調(diào)用FactoryBean的getObject方法獲取bean
object = getObjectFromFactoryBean(factory, beanName, !synthetic);
}
return object;
}
protected Object getCachedObjectForFactoryBean(String beanName) {
//factoryBeanObjectCache就是用來存放FactoryBean getObject生成的對(duì)象,此時(shí)還不包含我們需要的bean
return this.factoryBeanObjectCache.get(beanName);
}protected Object getObjectFromFactoryBean(FactoryBean<?> factory, String beanName, boolean shouldPostProcess) {
//單例且singletonObjects中已經(jīng)加載了FactoryBean
if (factory.isSingleton() && containsSingleton(beanName)) {
synchronized (getSingletonMutex()) {
//第一次進(jìn)來是獲取不到的
Object object = this.factoryBeanObjectCache.get(beanName);
if (object == null) {
//調(diào)用getObject,此時(shí)生成了Dog實(shí)例,打印“調(diào)用了Dog構(gòu)造器”
object = doGetObjectFromFactoryBean(factory, beanName);
// Only post-process and store if not put there already during getObject() call above
// (e.g. because of circular reference processing triggered by custom getBean calls)
Object alreadyThere = this.factoryBeanObjectCache.get(beanName);
if (alreadyThere != null) {
object = alreadyThere;
}
else {
if (shouldPostProcess) {
if (isSingletonCurrentlyInCreation(beanName)) {
// Temporarily return non-post-processed object, not storing it yet..
return object;
}
beforeSingletonCreation(beanName);
try {
//調(diào)用postProcessAfterInitialization,如果有AOP,此時(shí)生成代理對(duì)象
object = postProcessObjectFromFactoryBean(object, beanName);
}
catch (Throwable ex) {
throw new BeanCreationException(beanName,
"Post-processing of FactoryBean's singleton object failed", ex);
}
finally {
afterSingletonCreation(beanName);
}
}
if (containsSingleton(beanName)) {
//將Dog放到緩存中,下次就可以取到了
this.factoryBeanObjectCache.put(beanName, object);
}
}
}
return object;
}
}
else {
Object object = doGetObjectFromFactoryBean(factory, beanName);
if (shouldPostProcess) {
try {
object = postProcessObjectFromFactoryBean(object, beanName);
}
catch (Throwable ex) {
throw new BeanCreationException(beanName, "Post-processing of FactoryBean's object failed", ex);
}
}
return object;
}
}而要獲取MyFactoryBean就要通過“&myFactoryBean”才能獲取,getObjectForBeanInstance時(shí)通過BeanFactoryUtils.isFactoryDereference判斷beanName是不是以&開頭的,如果是,并且是FactoryBean類型的,則直接返回。
總結(jié)
FactoryBean本身作為bean保存在singletonObjects,beanName和普通bean一樣,首字母小寫(如果你沒指定的話)。
如果直接通過beanName獲取到的是FactoryBean通過getObject生成的對(duì)象,生成的對(duì)象保存在factoryBeanObjectCache中,便于下次獲取時(shí)不用再調(diào)用getObject。
如果想獲取FactoryBean本身,需要通過&beanName來獲取,容器根據(jù)前綴&和是否是FactoryBean,來從singletonObjects中獲取bean。
ObjectFactory是一個(gè)普通工程,通過getObject生成對(duì)象,不會(huì)像上面進(jìn)行緩存。
到此這篇關(guān)于Spring中的FactoryBean與ObjectFactory詳解的文章就介紹到這了,更多相關(guān)FactoryBean與ObjectFactory內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
利用Spring JPA中的@Version注解實(shí)現(xiàn)樂觀鎖
樂觀鎖是數(shù)據(jù)庫和應(yīng)用程序中使用的一種并發(fā)控制策略,用于在多個(gè)事務(wù)嘗試更新單個(gè)記錄時(shí)確保數(shù)據(jù)完整性,Java Persistence API (JPA) 提供了一種借助@Version注解在 Java 應(yīng)用程序中實(shí)現(xiàn)樂觀鎖的機(jī)制,文中有詳細(xì)的代碼示例供大家參考,需要的朋友可以參考下2023-11-11
java簡(jiǎn)單手寫版本實(shí)現(xiàn)時(shí)間輪算法
這篇文章主要為大家詳細(xì)介紹了java簡(jiǎn)單手寫版本實(shí)現(xiàn)時(shí)間輪算法,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-04-04
IntelliJ IDEA JRebel 安裝使用圖文教程(熱部署插件)
IDEA 全稱 IntelliJ IDEA,是java語言開發(fā)的集成環(huán)境,IntelliJ在業(yè)界被公認(rèn)為最好的java開發(fā)工具之一。這篇文章主要介紹了IntelliJ IDEA 熱部署插件JRebel 安裝使用圖文教程,需要的朋友可以參考下2018-03-03
SpringCloud全局過慮器GlobalFilter的用法小結(jié)
這篇文章主要介紹了SpringCloud全局過慮器GlobalFilter的使用,全局過慮器使用非常廣泛,比如驗(yàn)證是否登錄,全局性的處理,黑名單或白名單的校驗(yàn)等,本文結(jié)合示例代碼給大家介紹的非常詳細(xì),需要的朋友可以參考下2023-07-07
Java實(shí)現(xiàn)短信驗(yàn)證碼和國(guó)際短信群發(fā)功能的示例
本篇文章主要介紹了Java實(shí)現(xiàn)短信驗(yàn)證碼和國(guó)際短信群發(fā)功能的示例,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下。2017-02-02
Spring Boot Excel文件導(dǎo)出下載實(shí)現(xiàn)代碼
這篇文章帶領(lǐng)我們直接實(shí)現(xiàn)Excel文件的直接導(dǎo)出下載,后續(xù)開發(fā)不需要開發(fā)很多代碼,直接繼承已經(jīng)寫好的代碼,增加一個(gè)Xml配置就可以直接導(dǎo)出。具體實(shí)現(xiàn)代碼大家跟隨小編一起通過本文學(xué)習(xí)吧2018-11-11
Java自定義數(shù)組列表的實(shí)現(xiàn)操作
這篇文章主要介紹了Java自定義數(shù)組列表的實(shí)現(xiàn)操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧2020-09-09
java迭代器基礎(chǔ)知識(shí)點(diǎn)總結(jié)
在本篇內(nèi)容里小編給大家整理了一篇關(guān)于java迭代器基礎(chǔ)知識(shí)點(diǎn)總結(jié)內(nèi)容,有興趣的朋友們可以學(xué)習(xí)參考下。2021-01-01

