論 Spring 框架所運(yùn)用的設(shè)計模式
在當(dāng)今軟件開發(fā)的廣闊領(lǐng)域中,Spring 框架無疑占據(jù)著重要的一席之地。它以其強(qiáng)大的功能和靈活性,成為眾多開發(fā)者的得力助手。而在 Spring 框架的背后,蘊(yùn)含著一系列精妙絕倫的設(shè)計模式,這些設(shè)計模式猶如隱藏的智慧密碼,賦予了框架無盡的活力與魅力。
當(dāng)我們深入探究 Spring 框架時,就仿佛開啟了一扇通往軟件設(shè)計藝術(shù)殿堂的大門。其中的設(shè)計模式不僅是代碼組織和架構(gòu)的精巧構(gòu)建,更是對軟件開發(fā)理念的深刻詮釋。它們巧妙地解決了各種復(fù)雜問題,實(shí)現(xiàn)了代碼的高效復(fù)用、模塊的松散耦合以及系統(tǒng)的良好擴(kuò)展性。通過對 Spring 框架涉及的設(shè)計模式的剖析,我們將領(lǐng)略到設(shè)計智慧的熠熠光輝,感受它們?nèi)绾卧谲浖澜缰醒堇[出一場場精彩絕倫的代碼之舞,為構(gòu)建高質(zhì)量、可維護(hù)的軟件系統(tǒng)奠定堅實(shí)基礎(chǔ)。讓我們一同踏上這場探索 Spring 框架設(shè)計模式的奇妙之旅,去揭示其中的奧秘與精彩。
一、關(guān)于設(shè)計模式的一些只是鋪墊
1.軟件設(shè)計有哪些原則?
整體來說有七大原則:
- 開閉原則:對擴(kuò)展開放,對修改關(guān)閉。
- 里氏轉(zhuǎn)換:子類繼承父類時,除添加新的方法完成新增功能外,盡量不要重寫父類的方法。
- 依賴倒置: 高層類應(yīng)該依賴于底層類的抽象而不是具體。
- 合成復(fù)用:盡量使用對象組合/聚合,而不是繼承關(guān)系達(dá)到軟件復(fù)用的目的。
- 單一職責(zé):不要多于一個導(dǎo)致類變更的原因。
- 接口原則:用多個接口確定類的行為,而不是一個總接口定義所有行為。
- 迪米特法則:最少知道原則,一個類應(yīng)該盡可能減少對其他類的了解,避免類之間過度耦合。(其他類應(yīng)該封裝一個方法提供的該類使用)
2.設(shè)計模式分為哪幾類?有哪些設(shè)計模式
分類:
- 創(chuàng)建型模式:創(chuàng)建型模式主要用于創(chuàng)建對象。
- 結(jié)構(gòu)型模式:主要用于處理類或?qū)ο蟮慕M合。
- 行為型模式:主要用于描述對類或?qū)ο笤鯓咏换ズ驮鯓臃峙渎氊?zé)。
創(chuàng)建型模式:
- 單例模式:確保類有且只有一個對象被創(chuàng)建。
- 抽象工廠模式:允許客戶創(chuàng)建對象的宗族,而無需指定他們的具體類。
- 建造者模式:將一個復(fù)雜對象的構(gòu)建與它的表示分離,讓同樣的構(gòu)建過程而已創(chuàng)建不同的表示。
- 工廠方法模式:由類決定要創(chuàng)建的具體類是哪一個。
- 原型模式:用原型實(shí)例指定創(chuàng)建對象的種類,并且通過拷貝這個原型來創(chuàng)建新的對象。
結(jié)構(gòu)型模式:
- 適配器模式:封裝對象,并提供不同的接口。
- 橋接模式:將抽象部分和實(shí)現(xiàn)部分分離,讓他們獨(dú)立的變化。
- 裝飾模式:包裝一個對象,提供新的行為。
- 組合模式:客戶用一致的方式處理對象集合和單個對象。
- 外觀模式:簡化一群類的接口。
- 享元模式:運(yùn)用共享技術(shù)有效的支持大量細(xì)粒度的對象。
- 代理模式:包裝對象,以控制對此對象的訪問。
行為型模式:
- 模板方法模式:定義一個操作算法的總體架構(gòu),將一些步驟的實(shí)現(xiàn)放在子類中。
- 命令模式:封裝請求成為對象。
- 迭代器模式:在對象的集合之中游走,而不是暴露集合的實(shí)現(xiàn)。
- 觀察者模式:讓對象能夠在狀態(tài)改變時被通知。
- 中介者模式:用一個中介對象來封裝一系列的對象交互。中介者使各個對象不需要顯示的相互引用,從而使其耦合松散,而且可以獨(dú)立地改變他們之間的交互。
- 備忘錄模式:在不破壞封裝性的前提下,捕獲一個對象的內(nèi)部狀態(tài),并在該對象之外保存這個狀態(tài)。 以后就可以將該對象恢復(fù)到保存狀態(tài)。
- 解釋器模式:介紹給定一個語言,定義它的文法的一種表示,并定義一個解釋器, 該解釋器使用該表示來解釋語言中的句子。
- 狀態(tài)模式:封裝了基于狀態(tài)的行為,并使用委托在行為之間的切換。
- 策略模式:封裝可以互換的行為,并使用委托來決定要使用哪一個。
- 責(zé)任鏈模式:為了解除請求的發(fā)送者和接收者之間的耦合,使多個對象都有機(jī)會處理這個請求。將這些處理對象連成一個鏈,并沿著這個鏈傳遞該請求,直到一個對象處理它。
- 訪問者模式:一個作用于某對象結(jié)構(gòu)中的各元素的操作。它使你可以在不改變各元素的類的前提下定義作用于這些元素的新操作。
二、詳解Spring核心中的設(shè)計模式
1.為什么說Spring框架中的IOC是解耦的
從代碼層面來說,Spring通過控制反轉(zhuǎn)將對象之類依賴關(guān)系交由容器管理,如下所示我們的AService 依賴BService ,BService 可能還會依賴于CService 層層遞進(jìn),如果是傳統(tǒng)編碼,我們可能需要通過硬編碼的方式完成AService 的構(gòu)建。 而Spring通過IOC思想,在初始化階段將所有對象都交由三級緩存管理,將所有java bean初始化責(zé)任的實(shí)現(xiàn)細(xì)節(jié)轉(zhuǎn)移給Spring,使用時也只需指明接口類型,接口實(shí)現(xiàn)也無需關(guān)心,只需在配置層面中指定,而非通過硬編碼完成依賴管理:
所以我們使用時只需幾個簡單的配置和注解即可完成各種復(fù)雜的bean的依賴管理,這也就是開發(fā)層面對象依賴關(guān)系管理的解耦:
@Service("aService")
@Slf4j
public class AService {
@Autowired
private BService bService;
//......
}
從使用層面來說,Spring中的IOC也用到類似于門面模式的思想,將工具類的使用和創(chuàng)建剝離,整個工具類的創(chuàng)建過程對使用者來說是透明解耦的。
例如我們需要使用日志框架,在spring中我們只需給出簡單的配置,框架即在運(yùn)行時基于給定配置完成對應(yīng)的日志工具的注入(可以是log4j可以是slf4j或者其他日志框架),程序啟動后即可直接使用功能,無需關(guān)心創(chuàng)建和實(shí)現(xiàn):
2.Spring源碼中涉及的簡單工廠模式
簡單工廠模式的思想就是對外屏蔽創(chuàng)建對象的細(xì)節(jié),將對象的獲取統(tǒng)一內(nèi)聚到一個工廠類中,這一點(diǎn)在Spring中的ApplicationContext 發(fā)揮的淋漓盡致。 我們都知道Spring將所有java bean統(tǒng)一交由三級緩存進(jìn)行管理,使用時我們可以通過上下文或者需要的java bean,用戶只需按需要傳遞給工廠對應(yīng)的bean名稱即可得到自己需要的對象即可:
對應(yīng)的我們也給出使用示例:
@Autowired
private ApplicationContext applicationContext;
public Object getBean(String beanName) {
Object bean = applicationContext.getBean(beanName);
return bean;
}
3.Spring中的工廠方法模式
工廠方法模式適用于想讓工廠專注創(chuàng)建一個對象的場景,相較于簡單工廠模式,工廠方法模式思想是提供一個工廠的接口,開發(fā)者根據(jù)這個規(guī)范創(chuàng)建不同的工廠,然后按需使用不同的工廠創(chuàng)建不同的類即可。這種做法確保了工廠類也遵循開閉原則。
Spring中的FactoryBean就是工廠方法模式的典型實(shí)現(xiàn),如果我們希望容器中能夠提供一個可以創(chuàng)造指定類的工廠,那么我們就可以通過FactoryBean實(shí)現(xiàn)。 例如我們希望有一個工廠可以創(chuàng)建經(jīng)理,另一個工廠可以創(chuàng)建主管。那么我們就可以通過FactoryBean實(shí)現(xiàn)。 實(shí)現(xiàn)步驟如下,由于經(jīng)理和主管都是雇員類,所以我們創(chuàng)建一個雇員類:
//雇員類
public class EmployeeDTO {
private Integer id;
private String firstName;
private String lastName;
private String designation;
//Setters and Getters are hidden behind this comment.
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public String getDesignation() {
return designation;
}
public void setDesignation(String designation) {
this.designation = designation;
}
@Override
public String toString() {
return "Employee [id=" + id + ", firstName=" + firstName
+ ", lastName=" + lastName + ", type=" + designation + "]";
}
}
然后我們繼承FactoryBean接口實(shí)現(xiàn)一個工廠方法類,如下所示,可以看到如果我們可以根據(jù)傳入的designation決定創(chuàng)建的雇員類型。
public class EmployeeFactoryBean extends AbstractFactoryBean<Object> {
// 根據(jù)這個值決定創(chuàng)建主管還是經(jīng)理
private String designation;
public String getDesignation() {
return designation;
}
public void setDesignation(String designation) {
this.designation = designation;
}
//This method will be called by container to create new instances
@Override
protected Object createInstance() throws Exception {
EmployeeDTO employee = new EmployeeDTO();
employee.setId(-1);
employee.setFirstName("dummy");
employee.setLastName("dummy");
//Set designation here
employee.setDesignation(designation);
return employee;
}
//This method is required for autowiring to work correctly
@Override
public Class<EmployeeDTO> getObjectType() {
return EmployeeDTO.class;
}
}
兩種雇員的配置如下所示:
<!--factoryBean使用示例-->
<!--經(jīng)理工廠-->
<bean id="manager" class="com.study.service.EmployeeFactoryBean">
<property name="designation" value="Manager" />
</bean>
<!--主管工廠-->
<bean id="director" class="com.study.service.EmployeeFactoryBean">
<property name="designation" value="Director" />
</bean>
如果我們想創(chuàng)建director(主管)的工廠,那么我們的代碼就可以這樣使用,注意我們獲取bean時必須使用&,否則獲得的就不是EmployeeFactoryBean,則是EmployeeDTO
ApplicationContext context = new ClassPathXmlApplicationContext("spring-config.xml");
Object factory = context.getBean("&director");
System.out.println(factory);
//工廠方法模式,通過單一職責(zé)的工廠獲取專門的類
System.out.println(((EmployeeFactoryBean) factory).getObject());
當(dāng)然,如果想直接獲取高管或者經(jīng)理,獲取bean時不加&即可代碼如下所示即可:
ApplicationContext context = new ClassPathXmlApplicationContext("spring-config.xml");
EmployeeDTO manager = (EmployeeDTO) context.getBean("manager");
System.out.println(manager);
Object director = context.getBean("director");
System.out.println(director);
4.工廠方法模式相較于簡單工廠模式的優(yōu)缺點(diǎn)
工廠方法模式的優(yōu)點(diǎn):
- 符合開閉原則,相較于上面說到的簡單工廠模式來說,我們無需因?yàn)樵黾右粋€類型而去修改工廠代碼,我們完全可以通過實(shí)現(xiàn)一個新的工廠實(shí)現(xiàn)。
- 更符合單一職責(zé)的原則,對于單個類型創(chuàng)建的工廠邏輯更加易于維護(hù)。
缺點(diǎn):
- 針對特定類型都需要創(chuàng)建特定工廠,創(chuàng)建的類會增加,導(dǎo)致項(xiàng)目變得臃腫。
- 因?yàn)楣S方法的模式結(jié)構(gòu),維護(hù)的成本相對于簡單工廠模式會更高一些。
5.單例模式在Java中的使用優(yōu)勢
節(jié)省沒必要的創(chuàng)建對象的時間,由于是單例的對象,所以創(chuàng)建一次后就可以一直使用了,所以我們無需為了一個重量級對象的創(chuàng)建而耗費(fèi)大量的資源。
由于重量級對象的創(chuàng)建次數(shù)少了,所以我們就避免了沒必要的GC。從而降低GC壓力,避免沒必要的STW(Stop the World)導(dǎo)致的GC停頓。
6.Spring中單例模式的實(shí)現(xiàn)
Spring中獲取對象實(shí)例的方法即DefaultSingletonBeanRegistry中的getSingleton就是典型的Double-Checked Locking單例模式代碼:
@Nullable
protected Object getSingleton(String beanName, boolean allowEarlyReference) {
// Quick check for existing instance without full singleton lock
Object singletonObject = this.singletonObjects.get(beanName);
//一級緩存沒有需要的bean,進(jìn)入該邏輯
if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
singletonObject = this.earlySingletonObjects.get(beanName);
if (singletonObject == null && allowEarlyReference) {
//二級對象也沒有,上鎖進(jìn)入創(chuàng)建邏輯
synchronized (this.singletonObjects) {
// 再次檢查一級緩存也沒有,避免重復(fù)創(chuàng)建問題
singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null) {
//......
//創(chuàng)建對象存入二級緩存中
}
}
}
}
}
return singletonObject;
}
7.Spring中的代理模式
代理模式解耦了調(diào)用者和被調(diào)用者的關(guān)系,同時通過對原生類型的代理進(jìn)行增強(qiáng)易于拓展和維護(hù),Spring AOP就是通過代理模式實(shí)現(xiàn)增強(qiáng)切入,我們就以JDK代理為例查看Spring中的實(shí)現(xiàn):
public Object getProxy(@Nullable ClassLoader classLoader) {
// 忽略代碼
Class<?>[] proxiedInterfaces = AopProxyUtils.completeProxiedInterfaces(this.advised, true);
findDefinedEqualsAndHashCodeMethods(proxiedInterfaces);
//通過被代理的類的接口以及增強(qiáng)邏輯創(chuàng)建一個增強(qiáng)的用戶所需要的類
return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this);
}
查看newProxyInstance的實(shí)現(xiàn)即可看到j(luò)dk代理的傳統(tǒng)創(chuàng)建細(xì)節(jié)即拿到被代理的類類型和需要增強(qiáng)后的方法實(shí)現(xiàn)InvocationHandler 通過反射完成代理類創(chuàng)建:
@CallerSensitive
public static Object newProxyInstance(ClassLoader loader,
Class<?>[] interfaces,
InvocationHandler h)
throws IllegalArgumentException
{
//......
//獲取接口類類型
Class<?> cl = getProxyClass0(loader, intfs);
//......
//從緩存中獲取代理類的構(gòu)造方法
final Constructor<?> cons = cl.getConstructor(constructorParams);
final InvocationHandler ih = h;
//......
//基于InvocationHandler 和構(gòu)造方法完成代理類創(chuàng)建
return cons.newInstance(new Object[]{h});
} catch (IllegalAccessException|InstantiationException e) {
//......
} catch (InvocationTargetException e) {
//......
} catch (NoSuchMethodException e) {
throw new InternalError(e.toString(), e);
}
}
8.Spring中的模板方法模式
模板方法模式即固定一個算法骨架,抽象出某些可變的方法交給子類實(shí)現(xiàn),Spring的AbstractApplicationContext的refresh方法就是典型模板方法模式,
@Override
public void refresh() throws BeansException, IllegalStateException {
// 給容器refresh加鎖,避免容器處在refresh階段時,容器進(jìn)行了初始化或者銷毀的操作
synchronized (this.startupShutdownMonitor) {
// .........
try {
// .........
//定義了相關(guān)接口給用戶實(shí)現(xiàn),該方法會通過回調(diào)的方式調(diào)用這些方法,已經(jīng)實(shí)現(xiàn)好的細(xì)節(jié)
invokeBeanFactoryPostProcessors(beanFactory);
// 注冊攔截bean創(chuàng)建過程的BeanPostProcessor,已經(jīng)實(shí)現(xiàn)好的細(xì)節(jié)
registerBeanPostProcessors(beanFactory);
//模板方法的體現(xiàn),用戶可自定義重寫該方法
onRefresh();
//.......
}
// .......
}
}
9.模板方法模式的優(yōu)劣勢
優(yōu)勢很明顯:
- 算法骨架由父類定義,封裝不變,擴(kuò)展可變。
- 子類只需按需實(shí)現(xiàn)抽象類即可,易于擴(kuò)展維護(hù)。
- 提取了公共代碼,避免編寫重復(fù)代碼。
缺點(diǎn):
- 可讀性下降
- 可能會導(dǎo)致子類泛濫問題。
10.Spring中的觀察者模式
觀察者模式是一種行為型模式。 它表示的是一種主題與訂閱者之間具有依賴關(guān)系,當(dāng)訂閱者訂閱的主題狀態(tài)發(fā)生改變,會發(fā)送通知給響應(yīng)訂閱者,觸發(fā)訂閱者的響應(yīng)操作。
Spring 事件驅(qū)動模型就是觀察者模式很經(jīng)典的一個應(yīng)用。Spring 事件驅(qū)動模型非常有用,在很多場景都可以解耦我們的代碼。比如我們每次發(fā)布一個通知就需要某個用戶做出收到的響應(yīng),這個時候就可以利用觀察者模式來解決這個問題。
首先我們需要定義一個事件類:
public class DemoEvent extends ApplicationEvent {
private String msg;
public DemoEvent(Object source, String msg) {
super(source);
this.msg = msg;
}
public String getMsg() {
return msg;
}
public void setMsg(String msg) {
this.msg = msg;
}
}
然后創(chuàng)建一個監(jiān)聽器集成Spring框架的ApplicationListener,對DemoEvent進(jìn)行監(jiān)聽:
@Component
public class DemoListener implements ApplicationListener<DemoEvent> {
private static Logger logger = LoggerFactory.getLogger(DemoListener.class);
@Override
public void onApplicationEvent(DemoEvent event) {
logger.info("收到消息,消息內(nèi)容:{}", event.getMsg());
}
}
這樣我們發(fā)布事件后,監(jiān)聽器就接受并處理返回結(jié)果了:
@Autowired
private ApplicationContext applicationContext;
@Test
public void sendMsg() {
DemoEvent event = new DemoEvent(this, "你好");
applicationContext.publishEvent(event);
}
對應(yīng)輸出結(jié)果如下所示:
2022-11-22 13:03:15.814 INFO 15600 --- [ main] com.example.demo.DemoListener : 收到消息,消息內(nèi)容:你好
11.Spring中用到的適配器模式
適配器模式有用在在DisposableBeanAdapter適配統(tǒng)一處理bean銷毀上,因?yàn)槲覀僢ean銷毀方法可以通過xml配置也可以通過繼承DisposableBean接口實(shí)現(xiàn),所以這兩種不同的方法在銷毀時處理方式可能不一樣,所以我們可以通過適配器模式將這兩個處理邏輯封裝成統(tǒng)一適配器進(jìn)行處理
@Override
public void destroy() {
//......
//如果是接口實(shí)現(xiàn)則執(zhí)行該類實(shí)現(xiàn)的destroy方法
if (this.invokeDisposableBean) {
//......
try {
if (System.getSecurityManager() != null) {
//......
}
else {
//
((DisposableBean) this.bean).destroy();
}
}
catch (Throwable ex) {
//......
}
}
//如果有注解或者xml配置的方法,則走invokeCustomDestroyMethod進(jìn)行調(diào)用
if (this.destroyMethod != null) {
invokeCustomDestroyMethod(this.destroyMethod);
}
else if (this.destroyMethodName != null) {
Method methodToInvoke = determineDestroyMethod(this.destroyMethodName);
if (methodToInvoke != null) {
invokeCustomDestroyMethod(ClassUtils.getInterfaceMethodIfPossible(methodToInvoke));
}
}
}
12.Spring中的裝飾者模式
裝飾者模式即通過組合的方式對原有類的行為進(jìn)行一些擴(kuò)展操作即在開閉原則下的一種結(jié)構(gòu)型設(shè)計模式,就以Spring中的TransactionAwareCacheDecorator為例,它就是實(shí)現(xiàn)緩存支持事務(wù)的功能,繼承緩存接口,并將目標(biāo)緩存類組合進(jìn)來,保證原有類不被修改的情況下實(shí)現(xiàn)功能的擴(kuò)展:
//繼承Cache 類
public class TransactionAwareCacheDecorator implements Cache {
//行為需要擴(kuò)展的目標(biāo)類
private final Cache targetCache;
// 從接口那里獲得的put方法,通過對targetCache的put進(jìn)行進(jìn)一步封裝實(shí)現(xiàn)功能的包裝
@Override
public void put(final Object key, @Nullable final Object value) {
if (TransactionSynchronizationManager.isSynchronizationActive()) {
TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronizationAdapter() {
@Override
public void afterCommit() {
TransactionAwareCacheDecorator.this.targetCache.put(key, value);
}
});
}
else {
this.targetCache.put(key, value);
}
}
}
三、更多關(guān)于設(shè)計模式
1.什么是策略模式
策略模式是一種行為模式,它的作用主要是用于封裝那些動作一致,但是具體實(shí)現(xiàn)不一致的場景。例如我們現(xiàn)在有一個審核的動作,不同的人審核的方式不同。而且審核的行為會隨著時間推移不斷增加,單純使用if else去維護(hù)會使得代碼變得非常凌亂。 這時候使用策略模式定義一下相同的行為,讓子類去實(shí)現(xiàn)不同的策略,這樣的方式是最利于拓展的。
2.策略模式在Spring中如何使用
使用策略模式前,我們先需要使用接口固定一下策略的定義,例如我們現(xiàn)在要創(chuàng)建一個生成對象的策略createObj:
public interface CreateObjStrategy {
Object createObj();
}
對應(yīng)我們分別寫一個創(chuàng)建字符串對象和json對象的策略代碼:
@Component("createObj_str")
public class CreateStrObjStrategy implements CreateObjStrategy {
@Override
public Object createObj() {
Map<String, Object> map = new HashMap<>();
map.put("name", "xiaoming");
return JSONUtil.toJsonStr(map);
}
}
@Component("createObj_json")
public class CreateJsonObjStrategy implements CreateObjStrategy {
@Override
public Object createObj() {
JSONObject obj = new JSONObject();
obj.put("name", "zhangsan");
return obj;
}
}
到此為止,我們已經(jīng)完成了所有的策略的封裝,按照原生的策略模式的做法它會通過一個上下文來配置當(dāng)前策略,就像下面這張設(shè)計圖:
對應(yīng)我們給出封裝的代碼示例:
public class CreateJsonObjContext {
private CreateObjStrategy createObjStrategy;
public CreateJsonObjContext(CreateObjStrategy strategy) {
this.createObjStrategy = strategy;
}
public Object createObj() {
return createObjStrategy.createObj();
}
}
實(shí)際上有了Spring我們無需進(jìn)行顯示聲明創(chuàng)建了,我們可以通過配置、注解等方式指明本地程序需要注入的CreateObjStrategy 實(shí)現(xiàn),加載上下文的時候通過ApplicationContextAware這樣的擴(kuò)展點(diǎn)把bean取出來設(shè)置到CreateJsonObjContext 中:
@Component
public class CreateJsonObjContext implements ApplicationContextAware {
private CreateObjStrategy createObjStrategy;
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
//從容器中拿到由我們配置后容器中所設(shè)置的CreateObjStrategy設(shè)置到Context中
CreateObjStrategy bean = applicationContext.getBean(CreateObjStrategy.class);
createObjStrategy = bean;
}
public Object createObj() {
return createObjStrategy.createObj();
}
}
3.Spring中策略模式的運(yùn)用
最典型的就時InstantiationStrategy,Spring為其實(shí)現(xiàn)了兩種不同的策略,分別是CglibSubclassingInstantiationStrategy和SimpleInstantiationStrategy,在Spring通過實(shí)例化java bean的時候其內(nèi)部就會通過getInstantiationStrategy從上下文中獲取初始化策略instantiationStrategy,然后調(diào)用instantiationStrategy的instantiate完成bean的創(chuàng)建:
對應(yīng)的我們也給出AbstractAutowireCapableBeanFactory中instantiate實(shí)例化bean的實(shí)現(xiàn)印證這一說法:
private Object instantiate(String beanName, RootBeanDefinition mbd,
@Nullable Object factoryBean, Method factoryMethod, Object[] args) {
try {
else {
//通過getInstantiationStrategy獲取上下文中對應(yīng)的創(chuàng)建策略完成bean的創(chuàng)建
return this.beanFactory.getInstantiationStrategy().instantiate(
mbd, beanName, this.beanFactory, factoryBean, factoryMethod, args);
}
}
catch (Throwable ex) {
//......
}
}