When configuring multiple data sources using AbstractRoutingDataSource, it was found that DataSourceSwitchAspect configured using @aspect is always executed after a declarative transaction, and the configuration of Order still does not work. After investigation, it was found that it was due to the inconsistent AOP proxy methods of the two.
Inside spring, the automatic creation of the agent is completed through BeanPostProcessor (translated as postprocessor in the book "Spring Guide". According to the matching rules, it is roughly divided into three categories: 1. Automatically create a proxy for the matching bean to match the name of the bean, and implement the class BeanNameAutoProxyCreator 2. Automatically create a proxy based on the AspectJ annotation in the bean, and implement the class AnnotationAwareAspectJAutoProxyCreator 3. Automatically create a proxy based on the matching mechanism of the Advisor. All Advisors in the container will be scanned, and these sections will be automatically applied to the matching beans, and class DefaultAdvisorAutoProxyCreator is implemented.
Among them, the aop declared by @Aspect is proxyed through AnnotationAwareAspectJAutoProxyCreator, while the declarative transactions in the project are proxyed by BeanNameAutoProxyCreator. After debugging, it was found that the interception priority of BeanNameAutoProxyCreator is higher than that of AnnotationAwareAspectJAutoProxyCreator. The order configuration only works for the same type of aop interception method, as follows:
DataSourceSwitchAspect
/** * Data source switching facet* @author Matchstick */@Aspect@Order(1) //Make sure that the facet is executed before transaction @Componentpublic class DataSourceSwitchAspect{ private Logger logger = LoggerFactory.getLogger(getClass()); @Pointcut("@annotation(com.etu.multidatasource.test.datasource.DataSourceId)") public void pointcut(){} @Before("@annotation(dataSourceId)") public void switchDataSource(JoinPoint point, DataSourceId dataSourceId) { String dsId = dataSourceId.value(); MultiDataSourceContextHolder.setDataSourceId(dsId); logger.debug("switch datasource -> {}", dsId); } @After("@annotation(dataSourceId)") public void restoreDataSource(JoinPoint point, DataSourceId dataSourceId) { MultiDataSourceContextHolder.removeDataSourceId(); logger.debug("restore datasource -> {}", MultiDataSourceContextHolder.getDefaultDataSourceId()); }} DataSourceConfig
@Bean public BeanNameAutoProxyCreator txProxy() { BeanNameAutoProxyCreator creator = new BeanNameAutoProxyCreator(); creator.setInterceptorNames("txAdvice"); creator.setBeanNames("*Service", "*ServiceImpl"); creator.setProxyTargetClass(true); creator.setOrder(2); return creator; } Solution: Either modify the aop method of DataSourceSwitchAspect to be BeanNameAutoProxyCreator, or modify the transaction aop method to AnnotationAwareAspectJAutoProxyCreator. Since the data source switching aop is switched through annotation, the latter solution is selected, as follows:
DataSourceConfig
@Bean public AnnotationAwareAspectJAutoProxyCreator txProxy() { /* * AutoProxy in AspectJ method must be used, so as to maintain a unified aop interception method with DataSourceSwitchAspect, otherwise different interception methods will cause order failure*/ AnnotationAwareAspectJAutoProxyCreator c = new AnnotationAwareAspectJAutoProxyCreator(); c.setInterceptorNames("txAdvice"); c.setIncludePatterns(Arrays.asList("execution (public com.etu..*Service(..))")); c.setProxyTargetClass(true); c.setOrder(2); return c; } The above is all the content of this article. I hope it will be helpful to everyone's learning and I hope everyone will support Wulin.com more.