Arquitectura de Java a través del tren combinado con el código fuente para comprender PageHelper

¿Cómo implementar PageHelper?

  1. PageHelper primero guarda los parámetros pasados ​​por el front-end al objeto de la página, y luego almacena una copia de la página en ThreadLoacl, para garantizar que los parámetros no se afecten entre sí al paginar.
  2. Luego use el interceptor provisto por mybatis para obtener el valor de ThreadLocal, vuelva a ensamblar el SQL de paginación, agregue el parámetro de paginación en la instrucción sql a través del interceptor al ejecutar la consulta y luego implemente la consulta de paginación.
  3. Finalmente, los objetos almacenados en ThreadLocal se borran automáticamente en el segmento de código final.

Paso 1: Guardar página en ThreadLocal

public abstract class PageMethod {
    protected static final ThreadLocal<Page> LOCAL_PAGE = new ThreadLocal();
    ...

	public static <E> Page<E> startPage(int pageNum, int pageSize, boolean count, Boolean reasonable, Boolean pageSizeZero) {
		//page对象存储了如pageNum、pageSize、orderBy等查询条件
        Page<E> page = new Page(pageNum, pageSize, count);
        page.setReasonable(reasonable);
        page.setPageSizeZero(pageSizeZero);
        Page<E> oldPage = getLocalPage();
        if (oldPage != null && oldPage.isOrderByOnly()) {
            page.setOrderBy(oldPage.getOrderBy());
        }

        setLocalPage(page);//存储到ThreadLocal中
        return page;
    }

	protected static void setLocalPage(Page page) {
        LOCAL_PAGE.set(page);
    }

Depurar en esta posición, de hecho, Page.startpage ha completado lo que debe hacer, el siguiente paso es ejecutar selectByPrimaryKey()este método.
Inserte la descripción de la imagen aquí

El segundo paso: Interceptor de inyección SqlSessionFactory

Pasando a la siguiente oración de Debug selectByPrimaryKey(), llegamos a esta clase:

public class MapperProxy<T> implements InvocationHandler, Serializable {
	...
	public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        try {
            return Object.class.equals(method.getDeclaringClass()) ? method.invoke(this, args) : this.cachedInvoker(method).invoke(proxy, method, args, this.sqlSession);
        } catch (Throwable var5) {
            throw ExceptionUtil.unwrapThrowable(var5);
        }
    }
}

Independientemente del método que ocurra primero, solo mire InvocationHandler para comprender que este es un proxy dinámico.

En esta clase, Mybatis completó el proceso de inicialización:
Inserte la descripción de la imagen aquí
el proceso central de inicialización es leer el archivo de configuración en la instancia de Congiguration, y luego generar una instancia pública global SqlSessionTemplate para SqlSessionFactory.

public class SqlSessionFactoryBean implements FactoryBean<SqlSessionFactory>, InitializingBean, ApplicationListener<ApplicationEvent> {
	...
	private Interceptor[] plugins;

	protected SqlSessionFactory buildSqlSessionFactory() throws Exception {
		...
		if (!ObjectUtils.isEmpty(this.plugins)) {
            Stream.of(this.plugins).forEach((plugin) -> {
                targetConfiguration.addInterceptor(plugin);
                LOGGER.debug(() -> {
                    return "Registered plugin: '" + plugin + "'";
                });
            });
        }
		...
	}
}

En SqlSessionFactoryBean, notamos que sus propiedades contienen una matriz de Interceptor, y el buildSqlSessionFactory()método completa la inyección de Interceptor al agregar complementos a la Configuración.

Una vez completada la inicialización, el siguiente es el proceso de consulta de Mapper, que es una cadena de llamadas , de la siguiente manera: El
Inserte la descripción de la imagen aquí
núcleo es el método configuration.newExecutor (), que cargará la cadena de intercepción, que es el pageInterceptor.

El tercer paso: PageInterceptor para lograr la paginación

La lógica central de PageHelper está en PageInterceptor, PageInterceptor es un interceptor.

public class PageInterceptor implements Interceptor {
	private volatile Dialect dialect;
    private String countSuffix = "_COUNT";
    protected Cache<String, MappedStatement> msCountMap = null;
    private String default_dialect_class = "com.github.pagehelper.PageHelper";
    ...
}

Inserte la descripción de la imagen aquí

Publicado 431 artículos originales · elogiados 329 · 170,000 visitas

Supongo que te gusta

Origin blog.csdn.net/No_Game_No_Life_/article/details/105391744
Recomendado
Clasificación