Spring Data Jpa执行流程分析
本文章采用Customer类举例说明
Customer:
@Entity
@Table(name = "cst_customer")
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Customer {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "cust_id")
private Long custId;
@Column(name = "cust_name")
private String custName;
@Column(name = "cust_source")
private String custSource;
@Column(name = "cust_industry")
private String custIndustry;
@Column(name = "cust_level")
private String custLevel;
@Column(name = "cust_address")
private String custAddress;
@Column(name = "cust_phone")
private String custPhone;
}
CustomerDao:
public interface CustomerDao extends JpaRepository<Customer, Long>, JpaSpecificationExecutor<Customer> {
}
动态代理有4个角色,在Spring Data Jpa中分别为:
- 抽象角色:JpaRepository, JpaSpecificationExecutor
- 真实角色:SimpleJpaRepository
- 调用处理器:JdkDynamicAopProxy
- 代理角色:被注入到CustomerDao接口
其中代理角色和真实角色都实现了抽象角色
测试:
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = "classpath:spring-dao.xml")
public class MyTest {
@Autowired
private CustomerDao customerDao;
@Test
public void findOne() {
Customer customer = customerDao.findOne(31L);
System.out.println(customer);
}
}
在输出语句地方打个断点,可以看到customerDao被注入的是个SimpleJpaRepository的动态代理对象:
继续执行,会执行到JdkDynamicAopProxy(可以看到该类继承了InvocationHandler):
final class JdkDynamicAopProxy implements AopProxy, InvocationHandler, Serializable {
...
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
...
}
...
}
接着会调用SimpleJpaRepository中的findOne方法:
public class SimpleJpaRepository<T, ID extends Serializable> implements JpaRepository<T, ID>, JpaSpecificationExecutor<T> {
...
public T findOne(ID id) {
Assert.notNull(id, "The given id must not be null!");
Class<T> domainType = this.getDomainClass();
if (this.metadata == null) {
return this.em.find(domainType, id);
} else {
LockModeType type = this.metadata.getLockModeType();
Map<String, Object> hints = this.getQueryHints();
return type == null ? this.em.find(domainType, id, hints) : this.em.find(domainType, id, type, hints);
}
}
...
}
最后findOne方法中再调用实体管理器的find方法。