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的动态代理对象:

image-20210120151901239

继续执行,会执行到JdkDynamicAopProxy(可以看到该类继承了InvocationHandler):

final class JdkDynamicAopProxy implements AopProxy, InvocationHandler, Serializable {
    ...
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
		...
    }
    ...
}

image-20210120152529263

接着会调用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方法。

posted @ 2021-01-20 15:34  yhliln  阅读(529)  评论(0编辑  收藏  举报