泛型依赖注入

Spring 4.0版本中更新了很多新功能,其中比较重要的一个就是对带泛型的Bean进行依赖注入的支持。

泛型依赖注入允许我们在使用spring进行依赖注入的同时,利用泛型的优点对代码进行精简,同时在不增加代码的情况下增加代码的复用性。

Spring默认按照字段的类进行依赖注入,而Spring4的新特性就是把泛型的具体类型也作为类的一种分类方法(Qualifier)。

背景

假设有两个实体类StudentTeacher

@Data
public class Student implements IEntity{
private long id;
} @Data
public class Teacher implements IEntity{
private long id;
}

实体的存储,是通过仓储操作的,一般所有的实体仓储方法都是一致的,只有具体的实体类型不一样,定义仓储接口

public interface IRepository<TEntity extends IEntity>{
void add(TEntity entity);
List<TEntity> findAll();
...
}

定义仓储实现的基类,在本例中,使用List存储

public abstract class BaseRepository <TEntity extends IEntity> implements IRepository<TEntity>{
List<TEntity> datasource = new ArrayList<>();
@Override
public void add(TEntity entity){
this.datasource.add(entity);
} @Override
public List<TEntity> findAll(){
return datasource;
} }

泛型依赖注入的Bean

BaseRepository 是一个抽象类,不适宜注入到spring中,定义一个可以注入的bean

@Repository()
@Scope("prototype")
public class DefaultRepository<TEntity extends IEntity> extends BaseRepository<TEntity>{
}

注意@Scope("prototype")注解,表示DefaultRepository的bean的作用是瞬态的,每次获取bean时都会创建一个新的bean,如果不添加作用域,默认spring的bean是单例的,这样注入的仓储实例会是同一个实例。

test中依赖注入@Autowired IRepository<Student> studentRepository; @Autowired IRepository<Teacher> teacherRepository;,

验证这两个仓储的类型都是DefaultRepository类型,同时验证操作student不会影响到teacher


@ExtendWith(SpringExtension.class)
@ContextConfiguration(
classes = {DemoTests.DemoTestsConfiguration.class})
public class DemoTests { @Autowired
IRepository<Student> studentRepository; @Autowired
IRepository<Teacher> teacherRepository; @Test
public void test(){ assertThat(studentIRepository.getClass())
.isEqualTo(DefaultRepository.class);
assertThat(teacherIRepository.getClass())
.isEqualTo(DefaultRepository.class); studentIRepository.add(new Student()); assertThat(studentIRepository.findAll())
.hasSize(1); assertThat(teacherIRepository.findAll())
.hasSize(0);
} @ComponentScan({
"org.example"
})
@Configuration
public static class DemoTestsConfiguration {
} }

仓储扩展

在上一部分,所有的仓储操作,都定义在了BaseRepository中,如果遇到了仓储中未提供的方法,则需要对单个实体的仓储进行扩展。

自定义仓储接口,继承自IRepository<Student>

public interface IStudentRepository extends IRepository<Student>{
Student findById(long id);
}

实现自定义仓储接口

@Repository
public class StudentRepository extends BaseRepository<Student> implements IStudentRepository {
@Override
public Student findById(long id) {
return null;
}
}

使用例子如下


@ExtendWith(SpringExtension.class)
@ContextConfiguration(
classes = {DemoTests.DemoTestsConfiguration.class})
public class DemoTests { @Autowired
IRepository<Teacher> teacherRepository; @Autowired
IStudentRepository studentRepository; @Test
public void repositoryType(){ assertThat(studentRepository.getClass())
.isEqualTo(StudentRepository.class);
assertThat(teacherRepository.getClass())
.isEqualTo(DefaultRepository.class);
} @ComponentScan({
"org.example"
})
@Configuration
public static class DemoTestsConfiguration {
} }

总结

  1. 使用泛型依赖注入,可以减少重复代码和类的数目,在本例中,无需对StudentTeacher两个实体定义仓储接口和实现,使用统一的仓储接口和默认实现即可完成大部分的操作。
  2. 在项目中,我们使用mybatis-plus做为仓储层操作数据库,对实体的操作,都需要定义一个Mapper接口和一个Service接口,如果使用泛型注入,是否可以减少Service的代码量呢?
  3. 本文中使用的@Repository() @Scope("prototype") 两个注解注册仓储实例的Bean,@Scope("prototype")注解会导致每个实体的仓储都是瞬态的,如何保持每个实体对应的仓储Bean是同一个实例呢? 下一篇会介绍另外一种注册Bean的方式: spring bean的动态注入

关注我的公众号,一起探索新技术的海洋

spring泛型注入的更多相关文章

  1. Spring框架入门之Spring4.0新特性——泛型注入

    Spring框架入门之Spring4.0新特性——泛型注入 一.为了更加快捷的开发,为了更少的配置,特别是针对 Web 环境的开发,从 Spring 4.0 之后,Spring 引入了 泛型依赖注入. ...

  2. 【串线篇】spring泛型依赖注入原理

    spring泛型依赖注入原理 不管三七二十一 servlet :加注解@servlet service:加注解@service dao:加注解@Repository 这相当于在容器中注册这些个类

  3. spring注解方式配置以及spring4的泛型注入 (4)

    目录 一.@Controller 注解控制层(action) 二.@Service 注解服务层 三.@Repository 持久层 四.spring4的泛型注入测试 1 创建两个实体User和Role ...

  4. Spring 属性注入(二)BeanWrapper 结构

    Spring 属性注入(二)BeanWrapper 结构 Spring 系列目录(https://www.cnblogs.com/binarylei/p/10117436.html) BeanWrap ...

  5. Spring 属性注入(三)AbstractNestablePropertyAccessor

    Spring 属性注入(三)AbstractNestablePropertyAccessor Spring 系列目录(https://www.cnblogs.com/binarylei/p/10117 ...

  6. Spring自动注入properties文件

    实现spring 自动注入属性文件中的key-value. 1.在applicationContext.xml配置文件中,引入<util />命名空间. xmlns:util=" ...

  7. spring 属性注入

    Spring的核心技术室依赖注入,下面是依赖注入之属性注入的实现过程,牛刀小试,请看效果. 1.首先添加Spring.Web引用.本例中是使用分层思想来演示的,下面是项目的结构和UserModel类的 ...

  8. spring 多线程 注入 服务层 问题

    在用多线程的时候,里面要用到Spring注入服务层,或者是逻辑层的时候,一般是注入不进去的.具体原因应该是线程启动时没有用到Spring实例不池.所以注入的变量值都为null. 详细:http://h ...

  9. Spring 依赖注入方式详解

    平常的Java开发中,程序员在某个类中需要依赖其它类的方法. 通常是new一个依赖类再调用类实例的方法,这种开发存在的问题是new的类实例不好统一管理. Spring提出了依赖注入的思想,即依赖类不由 ...

随机推荐

  1. C语言之三字棋的简单实现及扩展

    C语言之三字棋的简单实现及扩展 在我们学习完数组之后,我们完全可以利用数组相关知识来写一个微小型的游戏,比如说今天所说的--三子棋. 大纲: 文件组成 实现   完整代码展示   扩展 即: 一.文件 ...

  2. Node.js 模块化你所需要知道的事

    一.前言 我们知道,Node.js是基于CommonJS规范进行模块化管理的,模块化是面对复杂的业务场景不可或缺的工具,或许你经常使用它,但却从没有系统的了解过,所以今天我们来聊一聊Node.js模块 ...

  3. Codeforces Round #685 (Div. 2)

    待补 A #include <bits/stdc++.h> using namespace std; int n; int main() { int __; scanf("%d& ...

  4. redis安装以及使用

    一.安装 1.源码安装 1.下载redis源码 $ wget http://download.redis.io/releases/redis-4.0.10.tar.gz 2.解压缩 $ tar -zx ...

  5. Django之缓存、信号和图片验证码、ORM性能

    一. 缓存 1. 介绍 缓存通俗来说:就是把数据先保存在某个地方,下次再读取的时候不用再去原位置读取,让访问速度更快. 缓存机制图解 2.Django中提供了6种缓存方式 1. 开发调试 2. 内存 ...

  6. shiro太复杂?快来试试这个轻量级权限认证框架!

    前言 在java的世界里,有很多优秀的权限认证框架,如Apache Shiro.Spring Security 等等.这些框架背景强大,历史悠久,其生态也比较齐全. 但同时这些框架也并非十分完美,在前 ...

  7. LAMP环境搭建与配置

    下载mysql 解压 运行错误 下载插件 启动成功 安装Apache 解压 报错  安装插件 再次报错 修改文档 成功 安装插件 下载 安装php 安装完成 解析php 安装完成 虚拟主机(共享主机, ...

  8. P1618 三连击(升级版)(JAVA语言)

    题目描述 将1,2,-,9共9个数分成三组,分别组成三个三位数,且使这三个三位数的比例是A:B:C,试求出所有满足条件的三个三位数,若无解,输出"No!!!". //感谢黄小U饮品 ...

  9. Activity类组成分析(一)Instrumentation

    目录 前言 解剖 继承关系 重要成员 Instrumentation 总结 前言 要了解清楚StartActivity的过程,Activity对象实例的构造过程是重要组成部分:而要弄清楚Activit ...

  10. 无法打开“&#215;&#215;&#215;”,因为无法确认开发者的身份——解决办法

    当打开这些应用程序时,系统提示无法打开" XXX",因为它来自身份不明的开发者.我们可以按照下面的方法解决. 教程 1.打开应用程序,找到你要打开的软件.按住control键,点击 ...