一直搞不懂栋哥的各种EQ啊EXIST啊什么的,说实话,我非常讨厌数据库和sql...
但是,逃不掉的,必须要看懂了 /(ㄒoㄒ)/~~
继承关系
先来一张图
首先,我们需要继承以加入框架
service
@Servicepublic class UserService extends DcBaseService{ @Autowired private UserRepo userRepo;}
repo
public interface UserRepo extends DcJpaRepository{}
service 和 repo 层的代码几乎什么都不用写。
场景
这里来看一次分页的过程。
UserService
调用父类 DcBaseService
的 queryPage
方法。
DcJpaRepository
代码
@NoRepositoryBeanpublic interface DcJpaRepositoryextends JpaRepository { Page queryPage(DcQuery var1); }
DcBaseService
代码
@Transactionalpublic class DcBaseService{ @Autowired private DcJpaRepository dcJpaRepository; public Page queryPage(DcQuery dcQuery) { return this.dcJpaRepository.queryPage(dcQuery); }}
DcBaseService
中的queryPage
方法中调用了自动注入的 dcJpaRepository
实例,但这个实例到底是什么呢?
回头来看,UserService
中的 userRepo
也是自动注入的。
对于dcJpaRepository
和userRepo
, userRepo
的类型是dcJpaRepository
的子类,User
也可以看成T
的子类, 那么,这两者应该是同一个实例,即子类实例userRepo
,但userRepo
的类型是接口,它的实例从哪来?
Debug
于是开始debug,两种情况如下
-
UserService
自有方法UserController
@GetMapping("/123")public void getAll(@PageableDefault Pageable page) { System.out.println(ticketService.ticketRepo); ticketService.findAllabc(); // ticketService.queryPage(null);}
UserService
public void findAllabc() { System.out.println(this.ticketRepo);}
由此可见,实例类型为
DcJpaRepositorySupport
,顺便看到了 Spring 的依赖,是在方法调用需要时才注入(想想都是一个很复杂的过程)。 -
DcBaseService
父类方法UserController
@GetMapping("/123")public void getAll(@PageableDefault Pageable page) { System.out.println(ticketService.ticketRepo); // ticketService.findAllabc(); ticketService.queryPage(null);}
DcBaseService
public Page
queryPage(DcQuery dcQuery) { return this.dcJpaRepository.queryPage(dcQuery);} 如图,实例类型还是
DcJpaRepositorySupport
。
通过以上两种情况,查看这个DcJpaRepositorySupport
源码如下
public class DcJpaRepositorySupportextends SimpleJpaRepository implements DcJpaRepository { public Page queryPage(DcQuery dcQuery) { return this.findAll(.......); }}
分析
Ok,再回头看最初的类图,推论如下:
-
正如直接写
UserRepo
继承JpaRepository
一样,后者定义的方法,如findOne
,是由SimpleJpaRepository
类来实现的。queryPage
是由DcJpaRepository
接口定义,DcJpaRepositorySupport
实现的。 -
因为多态,Spring 可以通过类型自动注入子类实例,而这个实现类,必然加持
@Repository
注解(或其它), 之所以DcJpaRepositorySupport
可以被注入,是因为它继承了SimpleJpaRepository
。 -
如果没有自定义的
Repository
实现,继承DcBaseService
的 service 可以不用再注入任何xxxRepo
,因为 Spring 根本就不会找上门来。