Record a BeanCurrentlyInCreationException caused by SqlSessionFactory

1. Project Overview

        The dependency of mybatis-plus-boot-starter is used in the project. In order to achieve the same processing of data permissions, a data permission interceptor is customized, which implements the Interceptor interface of mybatis (public class DataScopeInterceptor implements Interceptor). Shiro is also used in the project for permission processing.

2. Analysis

       Since ShiroFilterFactoryBean implements the BeanPostProcessor interface (spring extension interface), the bean instance is created first when the project starts. ShiroRealm in SecurityManager in ShiroFilterFactoryBean is a custom Realm (ShiroRealm).

ShiroRealm has injected a custom service, such as Aservice, and Aservice has injected Amapper. Because all mappers are injected into SqlSessionFactory, the process of loading beans when the project starts is as follows:

ShiroFilterFactoryBean"SecurityManager"ShiroRealm"Aservice"Amapper"SqlSessionFactory, and MybatisPlusAutoConfiguration is loaded when the SqlSessionFactory is created. There is a problem to note here, that is, the SqlSessionFactory bean is not placed in spring's three-level cache singletonFactories , loading MybatisPlusAutoConfiguration is All interceptors will be loaded, and our interceptor DataScopeInterceptor is injected with Bservice, and Bservice is injected with Bmapper, so the overall bean loading process is like this:

ShiroFilterFactoryBean》SecurityManager》ShiroRealm》Aservice》Amapper》SqlSessionFactory》MybatisPlusAutoConfiguration》DataScopeInterceptor 》Bservice》Bmapper》SqlSessionFactory

Since the SqlSessionFactory is loaded for the first time and is not placed in the singletonFactories of Spring's third-level cache, the SqlSessionFactory will be loaded again . Because every time a bean is created, the following processing will be done:

	protected void beforeSingletonCreation(String beanName) {
		if (!this.inCreationCheckExclusions.contains(beanName) && !this.singletonsCurrentlyInCreation.add(beanName)) {
			throw new BeanCurrentlyInCreationException(beanName);
		}
	}

So the method was successful the first time the SqlSessionFactory was created, but the second time, because there is already a SqlSessionFactory in singletonsCurrentlyInCreation, a BeanCurrentlyInCreationException was thrown.

Three, the solution

The first solution (recommended): add @Lazy to the Bservice that DataScopeInterceptor depends on

The second solution: Put Bservice into the first dependency of Aservice, Bservice is not used, but the idea is that there is no more Bmapper creation after DataScopeInterceptor. Of course, there can be no other mappers in the DataScopeInterceptor

Four, summary

        Since SqlSessionFactory "MybatisPlusAutoConfiguration, and SqlSessionFactory is not placed in the singletonFactories of spring's three-level cache, so before the completion of loading MybatisPlusAutoConfiguration, the SqlSessionFactory cannot be loaded again, that is, no other mappers can be loaded.

 

Guess you like

Origin blog.csdn.net/sinat_33472737/article/details/109503861