泛型依赖注入
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<>();@Overridepublic void add(TEntity entity){ this.datasource.add(entity);}@Overridepublic 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 {
@AutowiredIRepository<Student> studentRepository;@AutowiredIRepository<Teacher> teacherRepository;@Testpublic 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"})@Configurationpublic 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 {
@Overridepublic Student findById(long id) { return null;}
}
应用例子如下
@ExtendWith(SpringExtension.class)
@ContextConfiguration(
classes = {DemoTests.DemoTestsConfiguration.class})
public class DemoTests {
@AutowiredIRepository<Teacher> teacherRepository;@AutowiredIStudentRepository studentRepository;@Testpublic void repositoryType(){ assertThat(studentRepository.getClass()) .isEqualTo(StudentRepository.class); assertThat(teacherRepository.getClass()) .isEqualTo(DefaultRepository.class);}@ComponentScan({ "org.example"})@Configurationpublic static class DemoTestsConfiguration {}
}
总结
应用泛型依赖注入,能够缩小反复代码和类的数目,在本例中,无需对Student和Teacher两个实体定义仓储接口和实现,应用对立的仓储接口和默认实现即可实现大部分的操作。