배경
마스터-슬레이브 데이터베이스를 구성한 후 코드 수준에서 읽기-쓰기 분리를 어떻게 달성합니까?
사용자 정의 데이터베이스 라우팅
Spring 부트는 AbstractRoutingDataSource를 제공하여 사용자 정의 규칙에 따라 현재 데이터베이스를 선택하므로 쿼리를 실행하기 전과 실행 후에 읽기 슬레이브 라이브러리를 설정할 수 있습니다. 실행이 완료된 후, 메인 데이터베이스로 복원합니다.
동적으로 라우팅 가능한 데이터 소스를 구현하고 각 데이터베이스 쿼리 작업 전에 실행합니다. 구성 읽기
DbContextHolder.java
import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource; /** * @author songrgg * @since 1.0 */ public class ReadWriteSplitRoutingDataSource extends AbstractRoutingDataSource { @Override protected Object determineCurrentLookupKey() { return DbContextHolder.getDbType(); } }
AOP 최적화 코드
ReadOnlyConnection.java
/** * @author songrgg * @since 1.0 */ public class DbContextHolder { public enum DbType { MASTER, SLAVE } private static final ThreadLocal<DbType> contextHolder = new ThreadLocal<>(); public static void setDbType(DbType dbType) { if(dbType == null){ throw new NullPointerException(); } contextHolder.set(dbType); } public static DbType getDbType() { return contextHolder.get() == null ? DbType.MASTER : contextHolder.get(); } public static void clearDbType() { contextHolder.remove(); } }
ReadOnlyConnectionInterceptor.java
package com.wallstreetcn.hatano.config; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; /** * Indicates the database operations is bound to the slave database. * AOP interceptor will set the database to the slave with this interface. * @author songrgg * @since 1.0 */ @Target({ElementType.METHOD, ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) public @interface ReadOnlyConnection { }
import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.annotation.Around; import org.aspectj.lang.annotation.Aspect; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.core.Ordered; import org.springframework.stereotype.Component; /** * Intercept the database operations, bind database to read-only database as this annotation * is applied. * @author songrgg * @since 1.0 */ @Aspect @Component public class ReadOnlyConnectionInterceptor implements Ordered { private static final Logger logger = LoggerFactory.getLogger(ReadOnlyConnectionInterceptor.class); @Around("@annotation(readOnlyConnection)") public Object proceed(ProceedingJoinPoint proceedingJoinPoint, ReadOnlyConnection readOnlyConnection) throws Throwable { try { logger.info("set database connection to read only"); DbContextHolder.setDbType(DbContextHolder.DbType.SLAVE); Object result = proceedingJoinPoint.proceed(); return result; } finally { DbContextHolder.clearDbType(); logger.info("restore database connection"); } } @Override public int getOrder() { return 0; } }
compile("com.alibaba:druid:1.0.18")
groovy 종속성 주입
context.groovy
@ReadOnlyConnection public List<User> getUsers(Integer page, Integer limit) { return repository.findAll(new PageRequest(page, limit)); }
위 내용은 이 글의 전체 내용입니다. 모든 분들의 학습에 도움이 되길 바라며, PHP 중국어 홈페이지도 많은 응원 부탁드립니다.