Spring中接口FactoryBean作用及說明
簡述
Spring 容器中有兩種bean :
- 普通 Bean:Spring 使用反射機(jī)制,利用Class 屬性來實(shí)例化 Bean,放置到容器中
- 工廠Bean (實(shí)現(xiàn) FactoryBean): 當(dāng) Bean 的實(shí)例化過程比較復(fù)雜是,如果按照傳統(tǒng)的方式(XML),則需要提供大量的配置信息, 采用編碼的方式創(chuàng)建更加優(yōu)雅,用戶可以通過實(shí)現(xiàn) org.Springframework.bean.factory.FactoryBean 定制 bean 實(shí)例化過程
FactoryBean接口對于Spring框架來說占有重要的地位,Spring 自身就提供了很多FactoryBean的實(shí)現(xiàn)。它們隱藏了實(shí)例化一些復(fù)雜bean的細(xì)節(jié),給上層應(yīng)用帶來了便利。
從Spring 3.0 開始, FactoryBean開始支持泛型,即接口聲明改為FactoryBean 的形式。
Spring 官方文檔中對 FactoryBean介紹
You can implement the org.springframework.beans.factory.FactoryBean interface for objects that are themselves factories.
The FactoryBean interface is a point of pluggability into the Spring IoC container’s instantiation logic. If you have complex initialization code that is better expressed in Java as opposed to a (potentially) verbose amount of XML, you can create your own FactoryBean, write the complex initialization inside that class, and then plug your custom FactoryBean into the container.
The FactoryBean interface provides three methods:
- T getObject(): Returns an instance of the object this factory creates. The instance can possibly be shared, depending on whether this factory returns singletons or prototypes.
- boolean isSingleton(): Returns true if this FactoryBean returns singletons or false otherwise. The default implementation of this method returns true.
- Class<?> getObjectType(): Returns the object type returned by the getObject() method or null if the type is not known in advance.
The FactoryBean concept and interface are used in a number of places within the Spring Framework. More than 50 implementations of the FactoryBean interface ship with Spring itself.
When you need to ask a container for an actual FactoryBean instance itself instead of the bean it produces, prefix the bean’s id with the ampersand symbol (&) when calling the getBean() method of the ApplicationContext. So, for a given FactoryBean with an id of myBean, invoking getBean(“myBean”) on the container returns the product of the FactoryBean, whereas invoking getBean(“&myBean”) returns the FactoryBean instance itself.
簡述:
1.Spring 提供了 FactoryBean接口 供我們實(shí)現(xiàn),用于創(chuàng)建復(fù)雜的 Bean 對象, 避免復(fù)雜的XML配置
2.FactoryBean 中提供三個(gè) 方法:
- T getObject() : 返回該實(shí)現(xiàn)真正創(chuàng)建的 Bean, 非 FactoryBean 本身
- boolean isSingleton() : 決定 getObject() 是單例 還是 原型(多例),默認(rèn)是單例
- Class<?> getObjectType() : 返回 getObject() 對象 Class
3.Spring 框架內(nèi)部 也有50多個(gè)關(guān)于 FactoryBean 的實(shí)現(xiàn);
4.獲取對象
- 當(dāng)獲取 FactoryBean 創(chuàng)建的時(shí)對象, 可以使用 getBean(“myBean”);
- 當(dāng)獲取 FactoryBean 對象時(shí),需使用 getBean(“&myBean”)
實(shí)戰(zhàn)
MySqlSession類:后續(xù)交與 MySqlSessionFactory 初始化
package com.lot.learn.spring.factorybean;
import lombok.Data;
@Data
public class MySqlSession {
private Long id;
public MySqlSession(Long id) {
this.id = id;
}
}
MySqlSessionFactory 實(shí)現(xiàn) FactoryBean, 用于創(chuàng)建 MySqlSession
package com.lot.learn.spring.factorybean;
import lombok.Data;
import org.springframework.beans.factory.FactoryBean;
@Data
public class MySqlSessionFactory implements FactoryBean<MySqlSession> {
private Long id;
private Long sessionId;
@Override
public MySqlSession getObject() {
return new MySqlSession(sessionId);
}
@Override
public Class<?> getObjectType() {
return MySqlSession.class;
}
@Override
public boolean isSingleton() {
return true;
}
}
spring-factorybean.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">
<beans>
<bean id="mySqlSession" class="com.lot.learn.spring.factorybean.MySqlSessionFactory" >
<property name="id" value= "9999" />
<property name="sessionId" value= "1" />
</bean>
</beans>
</beans>Maven 配置 dependencies
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.2.9.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>5.2.9.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>5.2.9.RELEASE</version>
</dependency>
</dependencies>測試類: TestFactoryBean
package factorybean;
import com.lot.learn.spring.factorybean.MySqlSession;
import com.lot.learn.spring.factorybean.MySqlSessionFactory;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = { "classpath*:spring-factorybean.xml" })
public class TestFactoryBean {
@Autowired
private MySqlSessionFactory userFactory1;
@Autowired
private MySqlSession mySqlSession1;
@Autowired
private ApplicationContext context;
@Test
public void test() {
System.out.println("factory.getId() = " + userFactory1.getId());
// 我們并沒有配置 MySqlSession 仍可以注入
System.out.println("mySqlSession.getId() = " + mySqlSession1.getId());
// by Type
MySqlSession mySqlSession2 = context.getBean(MySqlSession.class);
MySqlSessionFactory userFactory2 = context.getBean(MySqlSessionFactory.class);
// by name
MySqlSession mySqlSession3 = (MySqlSession) context.getBean("mySqlSession");
MySqlSessionFactory userFactory3 = (MySqlSessionFactory) context.getBean("&mySqlSession");
// 以下都是 true
System.out.println("mySqlSession1 == mySqlSession2 :" + (mySqlSession1 == mySqlSession1));
System.out.println("userFactory1 == userFactory2 :" + (userFactory1 == userFactory1));
System.out.println("mySqlSession2 == mySqlSession3 :" + (mySqlSession2 == mySqlSession3));
System.out.println("userFactory2 == userFactory3 :" + (userFactory2 == userFactory3));
}
}
測試類執(zhí)行結(jié)果
根據(jù)打印結(jié)果看, 已經(jīng)驗(yàn)證上述問題
factory.getId() = 9999 mySqlSession.getId() = 1 mySqlSession1 == mySqlSession2 :true userFactory1 == userFactory2 :true mySqlSession2 == mySqlSession3 :true userFactory2 == userFactory3 :true
代替方案
現(xiàn)階段使用 FactoryBean 創(chuàng)建對象的使用習(xí)慣越來越少, 有很多其他更方便創(chuàng)建方式:
- @Configuration和@Bean注解配合,也可以用來創(chuàng)建bean,和FactoryBean的作用基本相同。但是@Bean功能更強(qiáng)大一些,可以支持懶加載,設(shè)置作用域等。
- @Component 也可
總結(jié)
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
解決Mybatis-Plus中分頁插件Page中total=0的問題
在使用Mybatis-Plus進(jìn)行分頁查詢時(shí),如果遇到`total=0`的情況,即使查詢到了數(shù)據(jù),也無法正確分頁,這通常是由于依賴版本問題導(dǎo)致的,對于低版本,需要手動(dòng)配置分頁攔截器;對于高版本,可能需要添加特定的依賴配置來解決這個(gè)問題2025-11-11
Spark SQL關(guān)于性能調(diào)優(yōu)選項(xiàng)詳解
這篇文章將為大家詳細(xì)講解有關(guān)Spark SQL性能調(diào)優(yōu)選項(xiàng),小編覺得挺實(shí)用的,因此分享給大家做個(gè)參考,希望大家閱讀完這篇文章后可以有所收獲2023-02-02
Java多線程工具CompletableFuture的使用教程
CompletableFuture實(shí)現(xiàn)了CompletionStage接口和Future接口,前者是對后者的一個(gè)擴(kuò)展,增加了異步回調(diào)、流式處理、多個(gè)Future組合處理的能力。本文就來詳細(xì)講講CompletableFuture的使用方式,需要的可以參考一下2022-08-08
詳解在Spring Boot框架下使用WebSocket實(shí)現(xiàn)消息推送
這篇文章主要介紹了詳解在Spring Boot框架下使用WebSocket實(shí)現(xiàn)消息推送,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下。2016-12-12
關(guān)于springboot集成swagger及knife4j的增強(qiáng)問題
這篇文章主要介紹了springboot集成swagger以及knife4j的增強(qiáng),本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2021-03-03
實(shí)現(xiàn)java文章點(diǎn)擊量記錄實(shí)例
這篇文章主要為大家介紹了實(shí)現(xiàn)java文章點(diǎn)擊量記錄實(shí)例,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-10-10
Java8?stream流分組groupingBy的使用方法代碼
對于java8的新特性groupingBy方法,相信有很多人都在工作中用過,這篇文章主要給大家介紹了關(guān)于Java8?stream流分組groupingBy的使用方法,需要的朋友可以參考下2024-01-01

