Hint forced routing custom annotation of ShardingSphere
1. Introduce dependency
<!--AOP--> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-aop</artifactId> </dependency> <!--context--> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> </dependency> <!--Faceted dependency package--> <dependency> <groupId>org.aspectj</groupId> <artifactId>aspectjweaver</artifactId> <scope>compile</scope> </dependency> <!--sharding Sub database and sub table routing--> <dependency> <groupId>org.apache.shardingsphere</groupId> <artifactId>sharding-core-route</artifactId> <version>4.0.0-RC1</version> </dependency>
2. Definition notes
@Retention(RetentionPolicy.RUNTIME) // Holding policies, which are recorded by the compiler in the class file and kept by the VM at runtime, can be read by reflection @Target(ElementType.METHOD) // Scope is method, that is, the annotation can only be used on method public @interface ShardingHint { /** * Set value * * @return value */ String value() default ""; /** * Fragment type * * @return ShardingTypeEnum */ ShardingTypeEnum type() default ShardingTypeEnum.DATABASE_ONLY; }
3. Define the section procedure
import org.apache.shardingsphere.api.hint.HintManager; import org.aspectj.lang.JoinPoint; import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.Signature; import org.aspectj.lang.annotation.*; import org.aspectj.lang.reflect.MethodSignature; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.stereotype.Component; import java.lang.reflect.Method; /** * <p> Forced routing</p> * * @author lijinghao * @version : BaseAdvice.java, v 0.1 2019 July 22, 2008 8:20:58 PM$ */ @Aspect @Component public class ShardingHintAdvice { private static final Logger logger = LoggerFactory.getLogger(ShardingHintAdvice.class); /** * Set tangent points */ @Pointcut("@annotation(com.u51.yacolpay.annotation.ShardingHint)") public void hintRoute() { } /** * Set forced route * * @param joinPoint Tangent point * @return results of enforcement * @throws Throwable abnormal */ @Around("hintRoute()") public Object setHintRoute(ProceedingJoinPoint joinPoint) throws Throwable { // How to get the annotation Method method = getCurrentMethod(joinPoint); // Get comments to process ShardingHint shardingHint = method.getAnnotation(ShardingHint.class); // Get the value in the annotation String value = shardingHint.value(); ShardingTypeEnum type = shardingHint.type(); if (logger.isDebugEnabled()) { logger.debug("Mandatory routing: type:{}, value:{}", type, value); } // processing program Object object; switch (type) { case DATABASE_ONLY: try (HintManager hintManager = HintManager.getInstance()) { hintManager.setDatabaseShardingValue(value); // Calling procedure object = joinPoint.proceed(); } break; case MASTER_ONLY: case DATABASE_TABLE: default: throw new RuntimeException("Annotation not yet supported Hint Routing mode"); } return object; } @Before("hintRoute()") public void beforeProcess() { // Pre call action } @Before("hintRoute()") public void afterProcess() { // Operation after calling } @AfterThrowing(pointcut = "hintRoute()", throwing = "e") public void doAfterThrowing(JoinPoint joinPoint, Throwable e) { // Can be used to handle exceptions } /** * Get current method * * @param pjp * @return * @throws Throwable */ private Method getCurrentMethod(ProceedingJoinPoint pjp) throws Throwable { Signature signature = pjp.getSignature(); if (!(signature instanceof MethodSignature)) { throw new IllegalArgumentException("This annotation can only be used for methods"); } MethodSignature methodSignature = (MethodSignature) signature; return pjp.getTarget() .getClass() .getMethod(methodSignature.getName(), methodSignature.getParameterTypes()); } }
4, configuration
4.1 enable AOP configuration
4.2 creating a Spring Bean
- Through automatic scanning, the shardinghintavice processing class needs to have @ Component annotation;
<!--Autoscan configuration--> <context:component-scan base-package="com.xxx.example"/>
- It can be configured through the bean tag of Spring.
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> <bean id="shardingDatabaseHintAdvice" class="com.u51.yacolpay.annotation.ShardingDatabaseHintAdvice"/> <bean id="hintStrategyAlgorithm" class="com.u51.yacolpay.hint.HintStrategyAlgorithm"/> </beans>
5, test
Because AOP is based on dynamic proxy, it needs to be called through interface.
Startup class:
public class SpringNamespaceMybatisExample { private static final String CONFIG_FILE = "META-INF/application-sharding-databases.xml"; public static void main(final String[] args) { try (ConfigurableApplicationContext applicationContext = new ClassPathXmlApplicationContext(CONFIG_FILE)) { SpringPojoService service = applicationContext.getBean(SpringPojoService.class); // When called through an interface, the configured AOP Hint annotation is valid service.printData(); } } }
Service category:
public interface SpringPojoService { void printData(); }
Implementation class:
@Service public class SpringPojoServiceImpl implements SpringPojoService { @Override // @ShardingHint(value = "test_0", type = ShardingTypeEnum.DATABASE_ONLY) @ShardingHint public void printData() { System.out.println("---------------------------- Print Order Data -----------------------"); for (Object each : orderRepository.selectAll()) { System.out.println(each); } } }
Test:
Break point in shardinghintavice to see if it is entered.
Here, the result of the sub database is that the Hint type is set, which will skip the SQL parsing and directly enter the Hint algorithm to complete the routing.
Other
This is only about the implementation of user-defined annotation, not to explain, there are many articles on the Internet.
Reference resources:
Official Spring documentation
Explanation of spring AOP custom annotation