今天使用数据源切换注解@DataSource的时候,发现没能成功切换,就在切换数据源的切面类里打了个断点,发现根本没切进去
下面时自定义的切面类,用Aspectj做的
@Pointcut("@annotation(com.skywell.common.annotation.DataSource)"
+ "|| @within(com.skywell.common.annotation.DataSource)")
public void dsPointCut() {
}
@Around("dsPointCut()")
public Object around(ProceedingJoinPoint point) throws Throwable {
DataSource dataSource = getDataSource(point);
if (StringUtils.isNotNull(dataSource)) {
DynamicDataSourceContextHolder.setDataSourceType(dataSource.value().name());
}
try {
return point.proceed();
} finally {
// 销毁数据源 在执行方法之后
DynamicDataSourceContextHolder.clearDataSourceType();
}
}
下面是我在serviceImpl上使用注解的代码
@DataSource(value = DataSourceType.OA)
@Override
public String importData(List<HrOaPermanentUserDTO> hrOaPermanentUserDTOList) {
return mapper.insert(hrOaPermanentUserDTOList)
}
很奇怪,按照切入点表达式,是肯定能切进去,定义了@DataSource注解的方法和类都应该能切到,但是我偏偏没切到
@Pointcut("@annotation(com.skywell.common.annotation.DataSource)"
+ "|| @within(com.skywell.common.annotation.DataSource)")
后来进过反复排查,发现原因是我在controller类上定义了@Transactional事务注解,导致了切面切不到
原因:controller上的@Transactional会生成一个代理对象,会包裹service实现类中的方法,而aspectj也是基于spring aop实现的,他生成的代理对象也会包裹service方法,这时就会导致代理对象冲突
但是由于@Transactional优先级高于其他注解,则导致@Transactional覆盖了@DataSource注解,使得@DataSource失效,也就导致不会走到切面类
解决方法:将@Transactional注解添加到Service接口中的方法上的方式,避免在Controller类上添加@Transactional注解,在Service实现类上添加@DataSource注解,这样可以避免代理对象的冲突,也可以保证切面类可以正确的切入到被切方法中。
在使用@DataSource注解进行数据源切换时,发现无法正常工作。问题出在@Controller类上的@Transactional注解创建了一个代理对象,导致@DataSource被覆盖,进而影响了切面处理。解决方法是将@Transactional移到Service接口的方法上,以避免代理对象冲突并确保切面正确切入。
957

被折叠的 条评论
为什么被折叠?



