一区二区三区在线-一区二区三区亚洲视频-一区二区三区亚洲-一区二区三区午夜-一区二区三区四区在线视频-一区二区三区四区在线免费观看

服務器之家:專注于服務器技術及軟件下載分享
分類導航

PHP教程|ASP.NET教程|Java教程|ASP教程|編程技術|正則表達式|C/C++|IOS|C#|Swift|Android|VB|R語言|JavaScript|易語言|vb.net|

服務器之家 - 編程語言 - Java教程 - Spring中初始化泛型類的方法實例

Spring中初始化泛型類的方法實例

2020-07-28 14:28隔葉黃鶯 Java教程

這篇文章主要給大家介紹了Spring中如何初始化泛型類,文中給出詳細的介紹和方法實例,對大家的理解和學習具有一定的參考借鑒價值,有需要的朋友可以參考學習,下面來一起看看吧。

首先來看下在 Java 中對于泛型類型,比如這樣簡單的類定義

?
1
class Processor<T> {}

如果直接初始化時要指定具體類型的話,我們可以這么寫

?
1
Processor<String> processor = new Processor<>(); //Java 7 及以上版本

Spring 對基本泛型的初始化

如果我們要用 Spring 容器來初始化這個類,比如給上面那個類加個 @Named 注解

?
1
2
3
@Named
class Processor<T> {
}

這時候我們通過 beanFactory.getBean(Processor.class) 得到的是一個什么樣的實例呢?Spring 怎么知道要指定什么具體類型呢?很簡單,任何不確定的情況都是 Object。所以通過容器得到的  Processor 實例相當于用下面代碼構造出來的

?
1
Processor processor = new Processor(); //更準確來講是 Processor<Object> processor = new Processor<>();

再進一步,對于有上限約束的泛型定義,Spring 才如何應對呢?像

?
1
2
3
@Named
class Processor<T extends Number> {
}

類似的,class Processor<T> 相當于 class Processor<T extends Object> , 因此 Spring 在具體類型未明的情況下也是要用最頂層可接受類型,Spring 將會針對上面的代碼實例出下面的對象

?
1
Processor<Number> processor = new Processor<>();

再復雜一些,泛型的子類型仍然是泛型的情況,如下代碼

首先定義了一個泛型接口

?
1
2
3
public interface Service<T> {
 String process(T t);
}

然后要求 Spring 容器來初始下面的 NumberService 實例

?
1
2
3
4
5
6
7
8
@Named
public class NumberService<R extends Number> implements Service<R> {
 
 @Override
 public String process(R number) {
 return "Process Number: " + number;
 }
}

Spring 在初始化 NumberService 實例同樣是要取用最頂層可接受類型,通過下面的代碼來初始化

?
1
NumberService<Number> numberService = new NumberService<>();

再終極一些,泛型類型并且類型也是泛型的,Spring 該如何拿捏?

?
1
2
3
4
5
6
@Named
public class Processor<T> {
 
 @Inject
 Private Service<T> service;
}

此時 Spring 該如何確定上面的類型 T 呢?因為有了 Service<T> service 屬性的存在而不能再籠統的想像 Spring 會采用下面的代碼來初始化 Processor 實例

?
1
Processor<Object> processor = new Processor<>();

而是 Processor 的具體類型必須通過被注入的 Service<T> 實例的具體類型來推斷的,這就取決于在 Spring 容器中存在什么樣的 Service<T> 實例。舉兩個例子

如果 Spring 中有初始化

?
1
2
3
4
5
6
7
@Named
public class StringService implements Service<String> {
 @Override
 public String process(String string) {
 return "Process String: " + string;
 }
}

那么前面的 Processor<T> 實例就相當于

?
1
2
Processor<String> processor = new Processor<>();
processor.service = new StringService();

如果 Spring 中初始化的 Service<T> 是前面那個 NumberService<R extends Number> implements Service<R> , 那么 Spring 容器中的 Processor<T> 實例相當于

?
1
2
Processor<Number> processor = new Processor<>();
processor.service = new NumberService<Number>();

那如果前面的 NumberService 和 StringService 同時在 Spring 容器中注冊了呢?Spring 同樣要為難了,在沒有 @Primary 的情況下無法確定使用哪個實例來注入 Service<T> service 屬性了,出現類似錯誤

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
2016-12-09 00:56:50.922 WARN 4950 --- [  main] s.c.a.AnnotationConfigApplicationContext : Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'processor': Unsatisfied dependency expressed through field 'service'; nested exception is org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type 'cc.unmi.Service<?>' available: expected single matching bean but found 2: numberService,stringService
2016-12-09 00:56:50.941 ERROR 4950 --- [  main] o.s.b.d.LoggingFailureAnalysisReporter :
 
***************************
APPLICATION FAILED TO START
***************************
 
Description:
 
Field service in cc.unmi.Processor required a single bean, but 2 were found:
 - numberService: defined in file [/Users/Yanbin/Workspaces/github/spring-generic-demo/target/classes/cc/unmi/NumberService.class]
 - stringService: defined in file [/Users/Yanbin/Workspaces/github/spring-generic-demo/target/classes/cc/unmi/StringService.class]
 
Action:
 
Consider marking one of the beans as @Primary, updating the consumer to accept multiple beans, or using @Qualifier to identify the bean that should be consumed

這和普通屬性的注入時有多個可選實例時是一樣的錯誤。

總結一下

如果 Spring 在初始化泛型類時,未提供任何具體類型則會采用最上限的類型來初始化實例

  1. @Named class Processor<T>  ->  new Processor<Object>()
  2. @Named class Processor<T extends Number> -> new Processor<Number>();

如果泛型類型與被注入的屬性的具體類型有關聯,則由屬性類型推斷出主類型

?
1
2
3
@Named class Processor<T> {
 @Inject Service<T> service;
}

此時 Spring 容器中存在 class StringService implements Service<String> 的實例,則會由屬性 service(StringService 實例) 推斷出 Processor 的具體類型是 Processor<String>

當然這個 Processor 類也是可以定義的稍復雜一些,如

?
1
2
3
@Named class Processor<T extends Number> {
 @Inject Service<T> service;
}

關于本文的示例代碼可參考 https://github.com/yabqiu/spring-generic-demo, 請運行 mvn spring-boot:run 查看輸出結果來理解 Spring 怎么去初始化泛型類實例的。

好了,以上就是這篇文章的全部內容了,希望本文的內容對大家學習或者使用Spring能帶來一定的幫助,如果有疑問大家可以留言交流。

原文鏈接:http://unmi.cc/how-spring-initialize-generic-object/

延伸 · 閱讀

精彩推薦
主站蜘蛛池模板: 成人欧美视频在线看免费 | 91大片淫黄大片在线天堂 | 91精品91 | 日本高清有码视频 | 被教官揉了一晚上的奶小说 | 日本人妖视频 | 国产精品福利在线观看免费不卡 | 1986葫芦兄弟全集免费观看第十集 | 嫩草影院地址一地址二 | 久久免费看少妇高潮A片特爽 | 午夜一区二区福利视频在线 | 52av我爱avhaose01 51香蕉视频 | sex5·性屋娱乐 | 香蕉eeww99国产精品 | 秋霞宅宅236理论片 秋霞一级黄色片 | 红楼影视h38bar在线线播放 | 果冻传媒和91制片厂网站软件 | 国产亚洲小视频 | 精品久久久久久 | 美女机机对机机的视频(免费) | 99热久久这里只有精品6国产网 | 日韩精品成人a在线观看 | 欧美18~20性hd| 秋葵污视频 | 国产毛片在线高清视频 | 99精品国产自产在线观看 | 色婷婷影院在线视频免费播放 | 国产亚洲精品美女2020久久 | 成人免费一区二区三区在线观看 | 无码乱人伦一区二区亚洲一 | 青青青视频蜜桃一区二区 | 国产精品原创视频 | 蜜桃传媒在线 | 国产一级黄色录像 | 欧美性黑人巨大gaysex | 兽操人 | 毛片免费网站 | 嫩草精品 | 天堂男人在线 | 麻生希在线观看 | 亚洲AV福利天堂一区二区三 |