精品欧美一区二区三区在线观看 _久久久久国色av免费观看性色_国产精品久久在线观看_亚洲第一综合网站_91精品又粗又猛又爽_小泽玛利亚一区二区免费_91亚洲精品国偷拍自产在线观看 _久久精品视频在线播放_美女精品久久久_欧美日韩国产成人在线

除了反射,還有其他方式初始化 Bean 嗎?

開發 前端
大家知道,Spring 中 Bean 的配置方式有很多種,但是正常來說,無論你是 XML 文件配置,還是用類似 @Service 注解這種配置,本質上最終都是通過反射去完成 Bean 的初始化的;@Bean 注解則稍微特殊一點,往往我們在 @Bean 注解中是自己 new 出來目標 Bean,但是 @Bean 注解所標記的方法也是通過反射調用的。

他提到他遇到了一個面試題,面試官問他:

  • Spring 中 Bean 的實例化有哪些方式?

大家知道,Spring 中 Bean 的配置方式有很多種,但是正常來說,無論你是 XML 文件配置,還是用類似 @Service 注解這種配置,本質上最終都是通過反射去完成 Bean 的初始化的;@Bean 注解則稍微特殊一點,往往我們在 @Bean 注解中是自己 new 出來目標 Bean,但是 @Bean 注解所標記的方法也是通過反射調用的。

似乎 Bean 的實例化離不開反射。

那么除了上面這些方案,還有沒有其他方案呢?松哥之前其實寫過一篇文章,今天再拎出來和小伙伴們分享一下。

以下內容基于 Spring6.0.4。

小伙伴們知道,當我們使用 Spring 容器的時候,如果遇到一些特殊的 Bean,一般來說可以通過如下三種方式進行配置:

  • 靜態工廠方法
  • 實例工廠方法
  • FactoryBean

不過從 Spring5 開始,在 AbstractBeandefinition 類中多了一個屬性,對于特殊的 Bean 我們有了更多的選擇:

/**
* Specify a callback for creating an instance of the bean,
* as an alternative to a declaratively specified factory method.
* <p>If such a callback is set, it will override any other constructor
* or factory method metadata. However, bean property population and
* potential annotation-driven injection will still apply as usual.
* @since 5.0
* @see #setConstructorArgumentValues(ConstructorArgumentValues)
* @see #setPropertyValues(MutablePropertyValues)
*/
public void setInstanceSupplier(@Nullable Supplier<?> instanceSupplier) {
this.instanceSupplier = instanceSupplier;
}

/**
* Return a callback for creating an instance of the bean, if any.
* @since 5.0
*/
@Nullable
public Supplier<?> getInstanceSupplier() {
return this.instanceSupplier;
}

接下來松哥就來和大家簡單聊一聊這個話題。

一、傳統解決方案

1.1 問題

不知道各位小伙伴們有沒有用過 OkHttp,這是一個專門做網絡請求的工具,在微服務的 HTTP 調用組件中,我們可以配置底層使用 OkHttp 這個工具。

一般來說,如果我們想直接使用 OkHttp,代碼如下:

OkHttpClient client = new OkHttpClient.Builder()
.connectTimeout(5, TimeUnit.SECONDS)
.readTimeout(5, TimeUnit.SECONDS)
.build();
Request getReq = new Request.Builder().get().url("http://www.javaboy.org").build();
Call call = client.newCall(getReq);
call.enqueue(new Callback() {
@Override
public void onFailure(@NotNull Call call, @NotNull IOException e) {
System.out.println("e.getMessage() = " + e.getMessage());
}
@Override
public void onResponse(@NotNull Call call, @NotNull Response response) throws IOException {
System.out.println("response.body().string() = " + response.body().string());
}
});

先通過建造者模式創建出來一個 OkHttpClient 對象,然后還是建造者模式創建出來 Request 對象,接下來去發送請求就可以了。那么對于這樣的代碼,我們可以將 OkHttpClient 對象交由 Spring 容器統一管理,那么該如何將 OkHttpClient 注冊到 Spring 容器中呢?

1.2 靜態工廠方法

首先可以采用靜態工廠方法,也就是工廠方法是一個靜態方法,如下:

public class OkHttpStaticFactory {
private static OkHttpClient okHttpClient;
static {
okHttpClient = new OkHttpClient.Builder()
.connectTimeout(5, TimeUnit.SECONDS)
.readTimeout(5, TimeUnit.SECONDS)
.build();
}
public static OkHttpClient getOkHttpClient() {
return okHttpClient;
}
}

然后在 Spring 配置文件中進行注入:

<bean class="org.javaboy.bean.OkHttpStaticFactory" factory-method="getOkHttpClient" id="httpClient"/>

靜態工廠的特點是靜態方法可以直接調用,并不必要獲取到工廠類的實例,所以上面配置的時候只需要指定 factory-method 就可以了。

這就可以了,將來我們去 Spring 容器中查找一個名為 httpClient 的對象,拿到手的就是 OkHttpClient 了。

1.3 實例工廠方法

實例工廠方法意思就是說工廠方法是一個實例方法。如下:

public class OkHttpInstanceFactory {
private volatile static OkHttpClient okHttpClient;

public OkHttpClient getInstance() {
if (okHttpClient == null) {
synchronized (OkHttpInstanceFactory.class) {
if (okHttpClient == null) {
okHttpClient = new OkHttpClient.Builder()
.connectTimeout(5, TimeUnit.SECONDS)
.readTimeout(5, TimeUnit.SECONDS)
.build();
}
}
}
return okHttpClient;
}
}

這是一個簡單的單例模式。但是這里的工廠方法是一個實例方法,實例方法的調用必須得先獲取到對象然后才能調用實例方法,因此配置方式如下:

<bean class="org.javaboy.bean.OkHttpInstanceFactory" id="httpInstanceFactory"/>
<bean factory-bean="httpInstanceFactory" factory-method="getInstance" id="httpClient"/>

好啦,接下來我們就可以去 Spring 容器中獲取一個名為 httpClient 的對象了,拿到手的就是 OkHttpClient 實例。

1.4 FactoryBean

當然,也可以通過 FactoryBean 來解決上述問題,FactoryBean 松哥在之前的文章中剛剛和大家介紹過,我們來看下:

public class OkHttpClientFactoryBean implements FactoryBean<OkHttpClient> {
@Override
public OkHttpClient getObject() throws Exception {
return new OkHttpClient.Builder()
.connectTimeout(5, TimeUnit.SECONDS)
.readTimeout(5, TimeUnit.SECONDS)
.build();
}

@Override
public Class<?> getObjectType() {
return OkHttpClient.class;
}

@Override
public boolean isSingleton() {
return true;
}
}

最后在 Spring 中配置即可:

<bean class="org.javaboy.bean.OkHttpClientFactoryBean" id="httpClient"/>

這個就不做過多解釋了,不熟悉的小伙伴可以翻看前面的文章。

上面這三種方案都是傳統方案。

特別是前兩種,其實我們用的比較少,前兩種有一個缺陷,就是我們配置的的 factory-method 都是通過反射來調用的,通過反射調用的話,多多少少性能受點影響。

這種 factory-method 在 Spring 中處理的源碼執行時序圖如下:

圖片圖片

所以最終反射是在 SimpleInstantiationStrategy#instantiate 方法中執行的,就是大家非常熟悉的反射代碼了:

@Override
public Object instantiate(RootBeanDefinition bd, @Nullable String beanName, BeanFactory owner,
@Nullable Object factoryBean, final Method factoryMethod, Object... args) {
ReflectionUtils.makeAccessible(factoryMethod);
Method priorInvokedFactoryMethod = currentlyInvokedFactoryMethod.get();
try {
currentlyInvokedFactoryMethod.set(factoryMethod);
Object result = factoryMethod.invoke(factoryBean, args);
if (result == null) {
result = new NullBean();
}
return result;
}
finally {
if (priorInvokedFactoryMethod != null) {
currentlyInvokedFactoryMethod.set(priorInvokedFactoryMethod);
}
else {
currentlyInvokedFactoryMethod.remove();
}
}
}

好了,這是傳統的解決方案。

二、Spring5 解決方案

Spring5 中開始提供了 Supplier,可以通過接口回調獲取到一個 Bean 的實例,這種方式顯然性能更好一些。

如下:

AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
GenericBeanDefinition definition = new GenericBeanDefinition();
definition.setBeanClass(Book.class);
definition.setInstanceSupplier((Supplier<Book>) () -> {
Book book = new Book();
book.setName("深入淺出 Spring Security");
book.setAuthor("江南一點雨");
return book;
});
ctx.registerBeanDefinition("b1", definition);
ctx.refresh();
Book b = ctx.getBean("b1", Book.class);
System.out.println("b = " + b);

關鍵就是通過調用 BeanDefinition 的 setInstanceSupplier 方法去設置回調。當然,上面這段代碼還可以通過 Lambda 進一步簡化:

public class BookSupplier {
public Book getBook() {
Book book = new Book();
book.setName("深入淺出 Spring Security");
book.setAuthor("江南一點雨");
return book;
}
}

然后調用這個方法即可:

AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
GenericBeanDefinition definition = new GenericBeanDefinition();
definition.setBeanClass(Book.class);
BookSupplier bookSupplier = new BookSupplier();
definition.setInstanceSupplier(bookSupplier::getBook);
ctx.registerBeanDefinition("b1", definition);
ctx.refresh();
Book b = ctx.getBean("b1", Book.class);
System.out.println("b = " + b);

這是不是更有一點 Lambda 的感覺了~

在 Spring 源碼中,處理獲取 Bean 實例的時候,有如下一個分支,就是處理 Supplier 這種情況的:

AbstractAutowireCapableBeanFactory#createBeanInstance

protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) {
// Make sure bean class is actually resolved at this point.
Class<?> beanClass = resolveBeanClass(mbd, beanName);
if (beanClass != null && !Modifier.isPublic(beanClass.getModifiers()) && !mbd.isNonPublicAccessAllowed()) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Bean class isn't public, and non-public access not allowed: " + beanClass.getName());
}
Supplier<?> instanceSupplier = mbd.getInstanceSupplier();
if (instanceSupplier != null) {
return obtainFromSupplier(instanceSupplier, beanName);
}
if (mbd.getFactoryMethodName() != null) {
return instantiateUsingFactoryMethod(beanName, mbd, args);
}
//...
return instantiateBean(beanName, mbd);
}

@Nullable
private Object obtainInstanceFromSupplier(Supplier<?> supplier, String beanName) {
String outerBean = this.currentlyCreatedBean.get();
this.currentlyCreatedBean.set(beanName);
try {
if (supplier instanceof InstanceSupplier<?> instanceSupplier) {
return instanceSupplier.get(RegisteredBean.of((ConfigurableListableBeanFactory) this, beanName));
}
if (supplier instanceof ThrowingSupplier<?> throwableSupplier) {
return throwableSupplier.getWithException();
}
return supplier.get();
}
}

上面 obtainFromSupplier 這個方法,最終會調用到第二個方法。第二個方法中的 supplier.get(); 其實最終就調用到我們自己寫的 getBook 方法了。

責任編輯:武曉燕 來源: 江南一點雨
相關推薦

2023-11-12 23:08:17

C++初始化

2025-04-25 11:25:00

SpringBean初始化

2024-10-29 11:27:27

2009-12-25 10:44:37

VDSL上網

2018-05-29 14:57:59

HashMap容量初始化

2022-12-02 08:48:16

CSS置灰網站

2015-08-10 14:54:57

公有云云安全數據加密

2023-04-08 14:22:16

Spring初始化對象

2020-10-25 17:11:29

JDK代理監控

2019-11-04 13:50:36

Java數組編程語言

2009-09-08 09:48:34

LINQ初始化數組

2009-11-11 15:29:15

ADO初始化

2021-03-12 10:30:11

SpringMVC流程初始化

2010-07-28 10:22:33

FlexApplica

2022-07-06 10:37:45

SpringServlet初始化

2020-12-03 09:50:52

容器IoC流程

2011-06-17 15:29:44

C#對象初始化器集合初始化器

2024-01-09 09:46:13

數據庫MySQL

2024-01-15 06:34:09

Gin鏡像容器

2022-03-16 11:11:37

SpringBean項目
點贊
收藏

51CTO技術棧公眾號

欧美日韩黑人| 成人免费看黄| www.一区二区| 国产精品黄页免费高清在线观看| 少妇的滋味中文字幕bd| 亚洲国产精品免费视频| 欧美视频中文在线看| 一区二区三区四区五区精品 | 亚洲视频www| www.xxxx精品| 特大黑人巨人吊xxxx| 国产免费av国片精品草莓男男| 香蕉乱码成人久久天堂爱免费| 亚洲国产午夜伦理片大全在线观看网站 | 韩国黄色一级片| 成人国产精品一区二区免费麻豆 | 91在线看视频| 99精品综合| 亚洲色图日韩av| 老司机av网站| 欧美激情福利| 色婷婷久久综合| 亚洲精品视频免费看| 久久精品a一级国产免视看成人| 亚洲影视综合| 久久久久久国产精品| www深夜成人a√在线| 亚洲人挤奶视频| 亚洲第一视频在线观看| 三级黄色片免费观看| 99久久久国产精品免费调教网站| 婷婷国产在线综合| 亚洲一区 在线播放| 欧美成人xxx| 国产精品欧美一区喷水| 欧美在线一区二区三区四区| 天天综合网天天综合| 丁香啪啪综合成人亚洲小说 | 久久综合色综合88| 精品亚洲欧美日韩| 日韩一卡二卡在线| 成人国产精品免费网站| 国产精品一区二区三区在线观| 国产又粗又黄视频| 久久福利资源站| 成人美女免费网站视频| 一二三四区在线| 老司机精品视频导航| 国产精品视频自拍| 亚洲视频在线观看一区二区| 日本伊人精品一区二区三区观看方式| 欧美做爰性生交视频| 精品人妻一区二区三区免费看| 国产一区二区三区的电影| 4p变态网欧美系列| 亚洲自拍一区在线观看| 视频一区二区三区中文字幕| 国产精国产精品| 一区二区视频网站| 国内精品自线一区二区三区视频| 亚洲www视频| 黄色一级a毛片| 91在线视频网址| 欧美视频1区| 日本不卡三区| 一区二区三区日韩精品| 欧美视频在线观看视频| 天天综合av| 欧美亚洲免费在线一区| 在线观看免费不卡av| 视频二区欧美毛片免费观看| 亚洲第一视频网| 免费福利视频网站| 忘忧草精品久久久久久久高清| 久久亚洲精品一区二区| 久久久久99精品| 久久久久看片| 亚洲一区二区三区xxx视频| 亚洲老妇色熟女老太| 91免费看片在线观看| 日韩在线三区| 青青草原av在线| 色婷婷久久久久swag精品 | 国产自产在线视频| 日韩三区在线| 精品乱码亚洲一区二区不卡| 91网站免费视频| 亚洲国产一成人久久精品| 性色av一区二区三区红粉影视| 不卡av电影在线| 国产一区二区三区免费观看| 国产一区精品在线| 秋霞成人影院| 狠狠躁夜夜躁人人爽超碰91| 一个色综合久久| 里番精品3d一二三区| 久久精品夜夜夜夜夜久久| 国产污污视频在线观看| 黄色日韩网站视频| 欧美日韩精品一区| 亚洲综合图区| 欧美日韩在线电影| 亚洲精品女人久久久| 日韩理论片av| 欧美在线视频在线播放完整版免费观看| 亚洲av首页在线| 超碰个人在线| 欧洲色大大久久| 性色av蜜臀av浪潮av老女人| 亚州av乱码久久精品蜜桃| 国产91|九色| 亚洲精品无amm毛片| 中文字幕亚洲区| 久久黄色片视频| 亚州一区二区| 久久久91精品国产| 国产精品午夜一区二区| 99免费精品在线| 男女裸体影院高潮| 欧美另类激情| 亚洲最大在线视频| 人人爽人人爽人人片av| jvid福利写真一区二区三区| 丰满人妻一区二区三区53号| 祥仔av免费一区二区三区四区| 日韩精品中文字幕在线观看 | 91精品福利| 国产91热爆ts人妖在线| 亚洲 欧美 自拍偷拍| 一个色在线综合| 亚洲男人天堂古典| 李丽珍裸体午夜理伦片| 欧美日韩a区| 亚洲专区中文字幕| 国产在线69| 欧美精品123区| 成年人二级毛片| 国产真实乱对白精彩久久| 亚洲精品在线免费看| 精品裸体bbb| 在线播放日韩欧美| www.亚洲激情| 国产日韩欧美电影| 国产精品一区二区羞羞答答| 亚洲专区视频| 国产成人a亚洲精品| 精品无人乱码| 欧美午夜寂寞影院| 黄色av免费播放| 久久精品久久综合| 三年中国中文在线观看免费播放| www欧美在线观看| 久久不射热爱视频精品| 亚洲国产精品视频在线| 亚洲一区二区三区不卡国产欧美| 91精品又粗又猛又爽| 在线日韩中文| 欧美另类网站| 亚洲国产aⅴ精品一区二区三区| 精品国产一区二区三区在线观看| 国产又色又爽又黄又免费| 1000部国产精品成人观看| 国产一级片中文字幕| 精品91视频| 九九九九精品九九九九| 成人做爰视频www网站小优视频| 在线观看欧美视频| 国产乱淫片视频| 亚洲一区二区三区小说| 亚洲av网址在线| 美日韩一级片在线观看| 久久福利一区二区| 亚州国产精品| 成人在线视频网站| 国产精品国精产品一二| 亚洲色图欧美制服丝袜另类第一页| 亚洲精品无码久久久久| 亚洲男帅同性gay1069| 人妖粗暴刺激videos呻吟| 日韩影院精彩在线| www.99riav| 国产videos久久| 91中文在线视频| 亚洲一二三四| 久久国产精品免费视频| 日本福利片高清在线观看| 欧美精品亚洲一区二区在线播放| 精品无码免费视频| 国产欧美日韩另类一区| 成人在线观看一区二区| 日韩中文字幕区一区有砖一区| 91精品国产吴梦梦| 国产精品午夜一区二区三区| 999国产在线| 日韩不卡在线| 国内精品久久久久影院 日本资源 国内精品久久久久伊人av | 少妇人妻好深好紧精品无码| 国产成人av影院| 国产免费又粗又猛又爽| 亚洲二区视频| 中文字幕一区二区三区最新 | 国产精品黄色片| 国外成人在线播放| 免费观看久久久久| 亚洲欧美国产va在线影院| 精品国产无码一区二区| 欧美在线观看视频一区二区 | 日韩中文字幕av电影| 成人在线免费高清视频| 日韩成人综合| 美国av一区二区三区| 中文字幕一区二区三区四区久久| 国产精品美女久久| 都市激情亚洲综合| 久久久人成影片一区二区三区| 日本在线播放| 国产午夜精品视频| 你懂的好爽在线观看| 欧美精品一区二区三区四区| 国产毛片在线视频| 欧美性受xxxx黑人xyx| 亚洲一区欧美在线| 亚洲小说欧美激情另类| 亚洲色婷婷一区二区三区| 亚洲国产精品黑人久久久| 国产女主播喷水高潮网红在线| 粉嫩蜜臀av国产精品网站| 久久久久亚洲av片无码v| 精品一区二区三区免费| 999在线观看| 捆绑紧缚一区二区三区视频| 欧美成人黄色网址| 日本va欧美va欧美va精品| 麻豆av免费在线| 亚洲免费婷婷| 欧美日韩中文在线观看| 国产综合精品久久久久成人av| 91亚洲精品久久久蜜桃网站| 精品1卡二卡三卡四卡老狼| 粉嫩aⅴ一区二区三区四区五区| 欧美一级片在线免费观看| 国产乱人伦偷精品视频免下载| 日韩 国产 一区| 国产精品一级片| 国产伦理在线观看| 成人免费视频app| 性久久久久久久久久久| 99精品视频在线播放观看| 给我免费观看片在线电影的| 99精品视频一区二区| 亚洲国产综合视频| 久久众筹精品私拍模特| 欧美特级黄色录像| 国产精品麻豆久久久| 久久国产高清视频| 亚洲色欲色欲www在线观看| 久久黄色小视频| 天天综合色天天综合| 久久夜色精品国产噜噜亚洲av| 色激情天天射综合网| 在线观看免费视频a| 91麻豆精品国产91久久久资源速度 | 欧美日韩18| 久久久999免费视频| 久久尤物视频| 手机av在线网| 国产a久久麻豆| 老司机福利av| 国产精品伦一区二区三级视频| 色欲一区二区三区精品a片| 亚洲美女淫视频| 欧美一二三区视频| 欧美在线你懂得| 99久久久久久久| 日韩激情在线视频| 国产午夜精品一区理论片| 久久久成人av| 九色porny丨入口在线| 国产精品精品久久久久久| 久久免费精品| 欧美一区激情视频在线观看| 亚洲第一偷拍| 成人综合视频在线| 国产一区二区伦理| 三级电影在线看| 亚洲女子a中天字幕| 二区视频在线观看| 欧美性受xxxx黑人xyx性爽| 亚洲乱码在线观看| 国产亚洲精品美女| 黄色成人在线网| 国产精品视频一区二区三区四| 欧美区一区二区| 日韩视频精品| 91久久久久| 天天综合成人网| 国产欧美精品国产国产专区| 久久黄色小视频| 欧美丰满美乳xxx高潮www| 天堂网www中文在线| 九九精品在线观看| 亚洲成人人体| 久久99国产精品| 午夜精品亚洲| 午夜剧场高清版免费观看| 久久亚洲春色中文字幕久久久| 国产少妇在线观看| 欧美日韩国产一区| 国产视频网站在线| 97国产suv精品一区二区62| 国产美女精品视频免费播放软件| 日本亚洲导航| 亚洲欧美大片| 小毛片在线观看| 亚洲综合久久久| 国产jzjzjz丝袜老师水多| 中文字幕亚洲欧美| 精品国产第一福利网站| 国产欧美日韩综合精品二区| 久久精品国内一区二区三区水蜜桃| 久久国产乱子伦免费精品| 播五月开心婷婷综合| 欧美日韩大片在线观看| 88在线观看91蜜桃国自产| 99青草视频在线播放视| 国产97在线亚洲| 色综合久久中文| 欧美 丝袜 自拍 制服 另类| 国产成人在线影院| 91香蕉视频在线播放| 91精品国产综合久久香蕉麻豆 | 欧美激情精品久久久久久变态| 中文字幕日本一区| 一区二区国产日产| 看片网站欧美日韩| 97在线观看视频免费| 4438x亚洲最大成人网| 调教视频免费在线观看| 国产欧美日韩综合精品| 欧美丰满日韩| caoporm在线视频| 亚洲日本在线观看| 国产又大又黄又爽| 欧美美女操人视频| 99精品国产一区二区三区2021 | 日韩av影片在线观看| sm性调教片在线观看| 精品一区二区国产| 午夜在线一区二区| 波多野结衣av在线观看| 欧美中文字幕一二三区视频| sese在线视频| 亚洲综合一区二区不卡| 欧美午夜一区| 女~淫辱の触手3d动漫| 一本一道久久a久久精品| 成a人片在线观看www视频| 国产精品小说在线| 自拍视频亚洲| 少妇户外露出[11p]| 日本丶国产丶欧美色综合| 亚乱亚乱亚洲乱妇| 99蜜桃在线观看免费视频网站| 亚洲午夜在线| 成人免费网站黄| 欧美久久久久久久久中文字幕| 欧美色图天堂| 日韩av一区二区在线| 国产午夜激情视频| 欧美一级在线观看| 韩国精品一区| 亚洲国产一区在线| 国产一区三区三区| 日韩欧美激情视频| 在线成人激情视频| 视频在线一区| 成人久久久久久久久| 国产精品入口麻豆九色| www三级免费| 日韩免费av一区二区| 亚洲国产老妈| 午夜理伦三级做爰电影| 欧美丰满美乳xxx高潮www| 国产精品13p| 亚洲精品视频一二三| 国产高清不卡二三区| www.国产com| 不用播放器成人网| 亚洲三级网址| 精品人妻一区二区乱码| 一本到一区二区三区| a在线免费观看| 任我爽在线视频精品一| 国产精品香蕉一区二区三区| 69亚洲精品久久久蜜桃小说| 九九精品视频在线| 奇米色欧美一区二区三区| 丰满少妇xbxb毛片日本| 欧美性做爰猛烈叫床潮| 激情黄产视频在线免费观看|