springboot的动态代理失效问题......

本文深入探讨了在SpringBoot环境下实现双数据源切换的难点与解决方案。作者在项目实践中遭遇数据源切换失败的问题,经过多次调试,发现特定场景下数据源切换异常,并最终定位到Shiro框架中注入的ServiceBean为问题根源。通过添加@Lazy注解解决了问题,实现了数据源的顺利切换。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

今天在做项目的时候,遇到了一个非常扯淡的问题,困扰了我大半天才解决。不得不说,springboot虽然简单,但是坑还是不少!

问题描述:

在整合springboot双数据源的时候,大致的步骤可以看我第一篇写的步骤,第一篇写的虽然是在SSM环境下搭建的,但是原理其实和springboot差不多。

然而我花了20分钟将双数据源给搭建完毕后,却出现了一个非常诡异的错误,就是在我的aop配置类上却出了问题。

这是我之前的配置写法,在springboot中我是转换为了一个配置类,却比这个xml配置要更加的简单。通过环绕通知判断定义的数据源注解的位置,从而根据反射得到mapper方法进行切换数据源

<aop:config>
    <!--设置事务的优先级-->
    <aop:aspect ref="dataSwitchAop" order="0">
        <!--拦截所有的service的方法-->
        <!--当然也可以拦截Controller方法,这里设置的是拦截service-->
        <aop:pointcut id="dataSourcePointcut" expression="execution(* com.ilongsay.service.*Service..*(..))"/>
        <aop:before method="intercept" pointcut-ref="dataSourcePointcut"/>
        <aop:after method="clearDataSource" pointcut-ref="dataSourcePointcut"/>
    </aop:aspect>
</aop:config>

springboot中的设置:但是在实际的操作中,我却发现,数据源根本切换不了啊,我明明在mapper上添加了这个dataSource的注解了啊。。。。。。。

@Aspect
@Order(1)
@Component
public class DataSourceAspect
{
    protected Logger logger = LoggerFactory.getLogger(getClass());

    @Pointcut("@annotation(com.xxxx.xxxx.annotation.DataSource)")
    public void dsPointCut()
    {

    }

    @Around("dsPointCut()")
    public Object around(ProceedingJoinPoint point) throws Throwable
    {
        MethodSignature signature = (MethodSignature) point.getSignature();

        Method method = signature.getMethod();

        DataSource dataSource = method.getAnnotation(DataSource.class);

        if (StringUtils.isNotNull(dataSource))
        {
            DynamicDataSourceContextHolder.setDateSoureType(dataSource.value().name());
        }

        try
        {
            return point.proceed();
        }
        finally
        {
            // 销毁数据源 在执行方法之后
            DynamicDataSourceContextHolder.clearDateSoureType();
        }
    }
}

然后不断地断点调试,发现这个注解加在Controller上就可以正常的切换数据源,放在service或者是mapper上就不行!

怒了。

继续断点各种测试,发现就是没有进入到这个切面中去!

怒了。

继续断点,不成功就不去吃饭。

怒了。

还是老老实实吃了饭再来调试吧

.....

还是先睡会儿再来调试吧

.....

醒了继续调试

.....

忽然灵光一闪,我换其他的service试一下,完全可以切换啊,为什么这个service就不行?

嗯.....

是不是其他地方有使用了这个Service bean?而service注入了这个mapper也导致使用不了?

对,就是这样.....

然后我开始找哪里有这个bean被引用,忽然想起来上个星期刚刚做了shiro整合cas单点登录的功能,等等,是不是在shiro中引用了?而且恰好我上个项目没有使用到shiro。

最后终于找到元凶。原来在shiro中定义的注入的ServiceBean都不能正常的切换数据源,包括它们引用的注入的mapper!

最后解决的办法就是:注入的上面加一个懒加载的注解@Lazy 的这个注解。

具体原因未知。

然后可以完美的进行数据库的切换

public class UserRealm extends AuthorizingRealm
{
    private static final Logger log = LoggerFactory.getLogger(UserRealm.class);

    @Lazy
    @Autowired
    private ISysMenuService menuService;

    @Lazy
    @Autowired
    private ISysRoleService roleService;

    @Lazy
    @Autowired
    private SysLoginService loginService;

    @Lazy
    @Autowired
    private OnlineSessionDAO onlineSessionDAO;

 

评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值