Spring宣言トランザクションと@Aspectのブロック順序の問題の解決

2723 ワード

AbstractRoutingDataSourceを使用してマルチデータソースを構成する場合、@aspectを使用して構成されたDataSourceSwitchAspectは常に宣言トランザクションの後に実行され、Orderを構成することは依然としてできません.調査の結果、両者のaopエージェント方式が一致していないためです.
Spring内部では、BeanPostProcessor(「spring攻略」という本では、ポストプロセッサと訳されています)によってエージェントの自動作成が完了します.マッチングルールによって大きく3つのカテゴリに分けられる:1、マッチングBeanの名前によってマッチングしたBeanのエージェントが自動的に作成され、実装クラスBeanNameAutoProxyCreator 2、実装クラスBeanのAspectJ注記に基づいてエージェントが自動的に作成され、実装クラスAnnotationAwareAspectJAutoProxyCreator 3、Advisorのマッチングメカニズムに基づいてエージェントが自動的に作成され、コンテナ内のすべてのAdvisorがスキャンされ、一致するBeanに自動的に適用されます.
ここで@Aspectで宣言されたaopは、A n o t i o n A w a r e A w e A s p e ctJAutoProxyCreatorによってエージェントされ、プロジェクト内の宣言トランザクションはBeanNameAutoProxyCreatorによってエージェントされています.デバッグにより、BeanNameAutoProxyCreatorのブロック優先度は、次のようになります.
DataSourceSwitchAspect
/**
 *        
 * @author Matchstick
 */
@Aspect
@Order(1) //      transaction    
@Component
public 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;
 }

ソリューション:DataSourceSwitchAspectのaop方式をBeanName AutoProxyCreatorに変更するか、トランザクションaop方式をN o t i o t ionAwareAspectJAutoProxyCreatorに変更するか、注釈によって実現されるデータソースによってaopを切り替えるため、後者のソリューションを選択しました.
DataSourceConfig
@Bean
 public AnnotationAwareAspectJAutoProxyCreator txProxy()
 {
 /*
  *     AspectJ   AutoProxy,     DataSourceSwitchAspect     aop    ,            order  
  */
 AnnotationAwareAspectJAutoProxyCreator c = new AnnotationAwareAspectJAutoProxyCreator();
 c.setInterceptorNames("txAdvice");
 c.setIncludePatterns(Arrays.asList("execution (public com.etu..*Service(..))"));
 c.setProxyTargetClass(true);
 c.setOrder(2);
 return c;
 }