泛型依赖注入

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. 死磕生菜 -- lettuce 间歇性发生 RedisCommandTimeoutException 的深层原理及解决方案

    0x00 起源 项目的一些微服务集成了 Spring Data Redis,而底层的 Redis 客户端是 lettuce,这也是默认的客户端.微服务在某些环境中运行很正常,但在另一些环境中运行就会间 ...

  2. PTE 准备之 Describe Image

    25s 准备时间:决定用什么模板,用模板cover那些信息点 Content: 数字和文字哪个多,就多说哪个,均匀覆盖 Fluency : 保持流利度 不要纠结时态,单复数,人称代词等 时间要求: 尽 ...

  3. Go语言学习笔记——Go语言的make的理解

    实例:https://tour.go-zh.org/moretypes/10 谢大<Go Web编程>书中的讲解https://github.com/astaxie/build-web-a ...

  4. BZOJ_2243 [SDOI2011]染色 【树链剖分+线段树】

    一 题目 [SDOI2011]染色 二 分析 感觉树链剖分的这些题真的蛮考验码力的,自己的码力还是不够啊!o(╯□╰)o 还是比较常规的树链剖分,但是一定记得这里的线段树在查询的时候一定要考虑链于链相 ...

  5. ch2_8_2求解幸运数问题

    思路:f(x)进行十进制每位相加,g(x)进行二进制每位相加,比较是否相等即可. 小明同学学习了不同的进制之后,拿起了一些数字做起了游戏.小明同学知道,在日常生活中我们最常用的是十进制数,而在计算机中 ...

  6. python学习8 文件的操作

    本文拷贝了on testing 的<python之文件操作:文件的读写>,只做学习之用 python的文件读写通过 一.用open函数 二.对文件读写操作 三.读取文件位置定位 1. op ...

  7. 复制粘贴Ctrl+C改为自定义单键

    目录 那一瞬间不想用Ctrl+C了 (一)搜索渠道 关键词搜索 (二)方案对比 (三)最终方案Ditto 使用方法 (四)案例 1. 替换Ctrl+C快捷键: 2. 将英文小写替换为大写: 那一瞬间不 ...

  8. MyBatis工程搭建&MyBatis实现Mapper配置查询

    一.MyMyBatis工程搭建 新建Maven项目:mybatis-demo 准备数据源 1 # 删除mybatis_demo数据库 2 drop database if exists mybatis ...

  9. TypeError: Can't convert 'int' object to str implicitly Python常见错误

    尝试连接非字符串值与字符串 想要字符串连接非字符串需要先进行强制转化 可以用str()函数 --------------------------------

  10. vue 快速入门 系列 —— vue 的基础应用(上)

    其他章节请看: vue 快速入门 系列 vue 的基础应用(上) Tip: vue 的基础应用分上下两篇,上篇是基础,下篇是应用. 在初步认识 vue一文中,我们已经写了一个 vue 的 hello- ...