热门标签 | HotTags
当前位置:  开发笔记 > 运维 > 正文

Spring中初始化泛型类的方法实例

这篇文章主要给大家介绍了Spring中如何初始化泛型类,文中给出详细的介绍和方法实例,对大家的理解和学习具有一定的参考借鉴价值,有需要的朋友可以参考学习,下面来一起看看吧。

首先来看下在 Java 中对于泛型类型,比如这样简单的类定义

class Processor {}

如果直接初始化时要指定具体类型的话,我们可以这么写

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

Spring 对基本泛型的初始化

如果我们要用 Spring 容器来初始化这个类,比如给上面那个类加个 @Named 注解

@Named
class Processor {
}

这时候我们通过 beanFactory.getBean(Processor.class) 得到的是一个什么样的实例呢?Spring 怎么知道要指定什么具体类型呢?很简单,任何不确定的情况都是 Object。所以通过容器得到的  Processor 实例相当于用下面代码构造出来的

Processor processor = new Processor(); //更准确来讲是 Processor processor = new Processor<>();

再进一步,对于有上限约束的泛型定义,Spring 才如何应对呢?像

@Named
class Processor {
}

类似的,class Processor 相当于 class Processor , 因此 Spring 在具体类型未明的情况下也是要用最顶层可接受类型,Spring 将会针对上面的代码实例出下面的对象

Processor processor = new Processor<>();

再复杂一些,泛型的子类型仍然是泛型的情况,如下代码

首先定义了一个泛型接口

public interface Service {
 String process(T t);
}

然后要求 Spring 容器来初始下面的 NumberService 实例

@Named
public class NumberService implements Service {
 
 @Override
 public String process(R number) {
 return "Process Number: " + number; 
 }
}

Spring 在初始化 NumberService 实例同样是要取用最顶层可接受类型,通过下面的代码来初始化

NumberService numberService = new NumberService<>();

再终极一些,泛型类型并且类型也是泛型的,Spring 该如何拿捏?

@Named
public class Processor {
 
 @Inject
 Private Service service;
}

此时 Spring 该如何确定上面的类型 T 呢?因为有了 Service service 属性的存在而不能再笼统的想像 Spring 会采用下面的代码来初始化 Processor 实例

Processor processor = new Processor<>();

而是 Processor 的具体类型必须通过被注入的 Service 实例的具体类型来推断的,这就取决于在 Spring 容器中存在什么样的 Service 实例。举两个例子

如果 Spring 中有初始化

@Named
public class StringService implements Service {
 @Override
 public String process(String string) {
 return "Process String: " + string;
 }
}

那么前面的 Processor 实例就相当于

Processor processor = new Processor<>();
processor.service = new StringService();

如果 Spring 中初始化的 Service 是前面那个 NumberService implements Service , 那么 Spring 容器中的 Processor 实例相当于

Processor processor = new Processor<>();
processor.service = new NumberService();

那如果前面的 NumberService 和 StringService 同时在 Spring 容器中注册了呢?Spring 同样要为难了,在没有 @Primary 的情况下无法确定使用哪个实例来注入 Service service 属性了,出现类似错误

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<&#63;>' 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  ->  new Processor()
  2. @Named class Processor -> new Processor();

如果泛型类型与被注入的属性的具体类型有关联,则由属性类型推断出主类型

@Named class Processor {
 @Inject Service service;
}

此时 Spring 容器中存在 class StringService implements Service 的实例,则会由属性 service(StringService 实例) 推断出 Processor 的具体类型是 Processor

当然这个 Processor 类也是可以定义的稍复杂一些,如

@Named class Processor {
 @Inject Service service;
}

关于本文的示例代码可参考 https://github.com/yabqiu/spring-generic-demo, 请运行 mvn spring-boot:run 查看输出结果来理解 Spring 怎么去初始化泛型类实例的。

好了,以上就是这篇文章的全部内容了,希望本文的内容对大家学习或者使用Spring能带来一定的帮助,如果有疑问大家可以留言交流。


推荐阅读
author-avatar
金花婆婆2502921867
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有