spring泛型注入
泛型依赖注入
Spring 4.0版本中更新了很多新功能,其中比较重要的一个就是对带泛型的Bean进行依赖注入的支持。
泛型依赖注入允许我们在使用spring进行依赖注入的同时,利用泛型的优点对代码进行精简,同时在不增加代码的情况下增加代码的复用性。
Spring默认按照字段的类进行依赖注入,而Spring4的新特性就是把泛型的具体类型也作为类的一种分类方法(Qualifier)。
背景
假设有两个实体类Student
和Teacher
@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 {
}
}
总结
- 使用泛型依赖注入,可以减少重复代码和类的数目,在本例中,无需对
Student
和Teacher
两个实体定义仓储接口和实现,使用统一的仓储接口和默认实现即可完成大部分的操作。 - 在项目中,我们使用
mybatis-plus
做为仓储层操作数据库,对实体的操作,都需要定义一个Mapper
接口和一个Service
接口,如果使用泛型注入,是否可以减少Service
的代码量呢? - 本文中使用的
@Repository() @Scope("prototype")
两个注解注册仓储实例的Bean,@Scope("prototype")
注解会导致每个实体的仓储都是瞬态的,如何保持每个实体对应的仓储Bean是同一个实例呢? 下一篇会介绍另外一种注册Bean的方式: spring bean的动态注入
关注我的公众号,一起探索新技术的海洋
spring泛型注入的更多相关文章
- Spring框架入门之Spring4.0新特性——泛型注入
Spring框架入门之Spring4.0新特性——泛型注入 一.为了更加快捷的开发,为了更少的配置,特别是针对 Web 环境的开发,从 Spring 4.0 之后,Spring 引入了 泛型依赖注入. ...
- 【串线篇】spring泛型依赖注入原理
spring泛型依赖注入原理 不管三七二十一 servlet :加注解@servlet service:加注解@service dao:加注解@Repository 这相当于在容器中注册这些个类
- spring注解方式配置以及spring4的泛型注入 (4)
目录 一.@Controller 注解控制层(action) 二.@Service 注解服务层 三.@Repository 持久层 四.spring4的泛型注入测试 1 创建两个实体User和Role ...
- Spring 属性注入(二)BeanWrapper 结构
Spring 属性注入(二)BeanWrapper 结构 Spring 系列目录(https://www.cnblogs.com/binarylei/p/10117436.html) BeanWrap ...
- Spring 属性注入(三)AbstractNestablePropertyAccessor
Spring 属性注入(三)AbstractNestablePropertyAccessor Spring 系列目录(https://www.cnblogs.com/binarylei/p/10117 ...
- Spring自动注入properties文件
实现spring 自动注入属性文件中的key-value. 1.在applicationContext.xml配置文件中,引入<util />命名空间. xmlns:util=" ...
- spring 属性注入
Spring的核心技术室依赖注入,下面是依赖注入之属性注入的实现过程,牛刀小试,请看效果. 1.首先添加Spring.Web引用.本例中是使用分层思想来演示的,下面是项目的结构和UserModel类的 ...
- spring 多线程 注入 服务层 问题
在用多线程的时候,里面要用到Spring注入服务层,或者是逻辑层的时候,一般是注入不进去的.具体原因应该是线程启动时没有用到Spring实例不池.所以注入的变量值都为null. 详细:http://h ...
- Spring 依赖注入方式详解
平常的Java开发中,程序员在某个类中需要依赖其它类的方法. 通常是new一个依赖类再调用类实例的方法,这种开发存在的问题是new的类实例不好统一管理. Spring提出了依赖注入的思想,即依赖类不由 ...
随机推荐
- 爬虫必知必会(4)_异步协程-selenium_模拟登陆
一.单线程+多任务异步协程(推荐) 协程:对象.可以把协程当做是一个特殊的函数.如果一个函数的定义被async关键字所修饰.该特殊的函数被调用后函数内部的程序语句不会被立即执行,而是会返回一个协程对象 ...
- FreeBSD csh shell 配置
在/etc/csh.cshrc里面加入: alias ls ls –G, 并重新登录 问:如何让FreeBSD的csh像bash那样按tab列出列出无法补齐的候选文件? 答:标准的方法是按Ctrl+D ...
- NIO三大组件之Buffer
什么是Buffer Buffer(这里并不是特指Buffer类)是一个存储数据的容器,与数组类似(其实底层依旧是用数组的结构来存储数据),但不同的是,Buffer对象提供了一组更有效的方法去进行写入和 ...
- Mybatis最权威的知识点
1.什么是Mybatis? (1)Mybatis是一个半ORM(对象关系映射)框架,它内部封装了JDBC,开发时只需要关注SQL语句本身,不需要花费精力去处理加载驱动.创建连接.创建statement ...
- 从yield到yield from再到python协程
yield 关键字 def fib(): a,b = 0,1 while 1: yield b a,b = b,a+b yield是在:PEP 255 -- Simple Generators 这个p ...
- Android中的TaskStack及启动模式
目录 前言 如何观察ActivityStack? 几个问题 关键类介绍 ActivityStack的创建与种类 不同启动模式 launchMode Standard SingleTop SingleT ...
- PTA 统计二叉树结点个数
6-1 统计二叉树结点个数 (10 分) 本题要求实现一个函数,可统计二叉树的结点个数. 函数接口定义: int NodeCount ( BiTree T); T是二叉树树根指针,函数NodeCo ...
- 当红开发语言Go,真的是未来的技术主流吗?
摘要:文将详细介绍 Golang 的语言特点以及它的优缺点和适用场景,带着上述几个疑问,为读者分析 Go 语言的各个方面,以帮助初入 IT 行业的程序员以及对 Go 感兴趣的开发者进一步了解这个热门语 ...
- 【10.5NOIP普及模拟】sort
[10.5NOIP普及模拟]sort 文章目录 [10.5NOIP普及模拟]sort 题目描述 输入 输出 输入输出样例 样例输入 样例输出 数据范围限制 解析 code 题目描述 小x和小y是好朋友 ...
- 答应我,别在go项目中用init()了
前言 go的 init函数给人的感觉怪怪的,我想不明白聪明的 google团队为何要设计出这么一个"鸡肋"的机制.实际编码中,我主张尽量不要使用init函数. 首先来看看 init ...