Exploring the principle of spring-data-jpa (1) - Creating and loading the Repository interface in the runtime environment

spring-data-jpa has many advantages, such as inheriting the Repository interface, writing JPQL statements in annotations to access the database; supporting method name resolution to access the database; using Predicate to support dynamic queries, etc., which are not listed here. These are the advantages of using spring-data-jpa. If you want to use it better and more elegantly, you must explore the loading and running mechanism of spring-data-jpa.
The author of this article looks at the source code of spring-data-jpa and refers to the javadoc document, so there will inevitably be errors and omissions in the article. Readers are kindly requested to point out. Enter the topic below.

1. The runtime environment creates and loads the Repository interface
spring-data-jpa to seamlessly connect with the springframework framework at runtime. When using spring's @Repository annotation to generate a Repository instance, the Repository interface is instantiated using a dynamic proxy class and placed in the spring container for use.
The following is the class diagram of RepositoryFactoryBeanSupport and RepositoryFactorySupport, which play an important role in spring-data-jpa:


The role of RepositoryFactoryBeanSupport is that the adapter developed for spring's FactoryBean interface can easily configure the repository factory through spring; and the role of RepositoryFactorySupport is, Creates a factory bean given an instance of the repository interface. Create a proxy that implements the configured repository interface and apply an advice to pass control to the QueryExecuterMethodInterceptor.

By looking at the source code, we can see that a private RepositoryFactorySupport class variable is held in RepositoryFactoryBeanSupport. When the RepositoryFactoryBeanSupport.afterPropertiesSet() method is executed, a new JpaRepositoryFactory instance is created and assigned to the class variable factory (RepositoryFactorySupport) through the createRepositoryFactory() method. , look at the constructor of JpaRepositoryFactory, you can see that it holds instances such as entityManager for the convenience of later use.

The private T initAndReturn() in RepositoryFactoryBeanSupport is another fairly important method. The method description is:
Returns the previously initialized repository proxy or creates and returns the proxy if previously uninitialized. Returns the previously instantiated repository proxy instance, or, if previously If not instantiated, a proxy instance is generated and returned.
Why do you say so? Let's look at the code. This method is called by two other methods, one is afterPropertiesSet(), which is a loading method that needs to be implemented to implement the InitialingBean interface, which is usually called first; the other is getObject() that needs to be implemented to implement the FactoryBean interface. method, which is called at runtime and returns an instance of the Repository interface. So, in general initAndReturn() will have at least two chances to be called. The implementation of initAndReturn() is relatively simple:
private T initAndReturn() {
	Assert.notNull(repositoryInterface, "Repository interface must not be null on initialization!");

	if (this.repository == null) {
		this.repository = this.factory.getRepository(repositoryInterface, customImplementation);
	}

	return this.repository;
}

Obtain a org.springframework.data.jpa.repository.support.SimpleJpaRepository proxy class instance (defined as generic T extends Repository) through getRepository(repositoryInterface, customImplementation) of RepositoryFactorySupport (JpaRepositoryFactory instance), when constructing this instance, perform A series of running environment preparations are made:
Obtain an instance of the Query lookup strategy class QueryLookupStrategy (usually an instance of CreateIfNotFoundQueryLookupStrategy here) in the internal class QueryExecutorMethodInterceptor of RepositoryFactorySupport, and then execute resolveQuery(method, repositoryInformation, factory, namedQueries); Put it into the class variable queries of RepositoryFactorySupport (JpaRepositoryFactory instance), a ConcurrentHashMap<Method, RepositoryQuery>.
The following figure is the class diagram of QueryLookupStrategy:

When constructing a RepositoryQuery instance, it corresponds to a JpaQueryMethod instance, and the RepositoryQuery instance is actually a SimpleJpaQuery instance.

In summary, the above description is a JpaRepositoryFactoryBean instance generated by the spring framework (note that it is not generated by injection) that implements the InitialzingBean interface, and generates a SimpleJpaRepository proxy instance when the public void afterPropertiesSet() method is called. The SimpleJpaRepository instance holds the instantiated Repository proxy class and multiple JpaQueryMethods instantiated in the QueryExecutorMethodInterceptor constructor. As the name suggests, JpaQueryMethod is jpa's method data storage class annotated with @Query, so how many Repository interfaces are there? A method, it will contain how many JpaQueryMethod instances are added to the listening sequence.

Guess you like

Origin http://10.200.1.11:23101/article/api/json?id=326858952&siteId=291194637