一、问题如下:

  使用的是SpringBoot框架:通过AOP和自定义注解完成druid连接池的动态数据源切换(三)中的两个数据库spring_boot_demoother_data

  在UserController中同时调用两个方法getAgeOfUser()和getAgeOfUser2(),这里方法里都是使用UserService中的同一方法接收数据。

  不同的是在getAgeOfUser2()上使用了DataSource(DataSourceName.SECOND)自定义注解来切换数据源,当两个方法同时被调用时,代码如下:

package com.example.demo.controller;

import com.example.demo.annotation.DataSource;
import com.example.demo.enums.DataSourceName;
import com.example.demo.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* @author 我命倾尘
*/
@RestController
public class UserController { @Autowired
UserService userService; /**
* 从spring_boot_demo数据库中得到数据
* @return int
*/
public int getAgeOfUser(){
return userService.getAgeByUsername("springbootdemo");
} /**
* 从other_data数据库中得到数据
* @return
*/
@DataSource(DataSourceName.SECOND)
public int getAgeOfUser2(){
return userService.getAgeByUsername("springbootdemo");
} /**
* 两个方法同时执行
* @return String
*/
@RequestMapping("/user/age")
public String getAge(){
int age1=getAgeOfUser();
int age2=getAgeOfUser2();
return "spring_boot_demo:"+age1+";other_data:"+age2;
}
}

  得到的运行结果如下:

  

  很显然,切换数据源没有成功,加了切换注解的方法得到的显示结果还是主数据源的数据。

二、问题思考:

  相比于之前使用单方法切换数据源成功的测试结果,这次的测试和之前的差别无非以下两点:

  1、不使用注解(即默认数据源)的方法和使用注解(切换辅数据源)的方法同时被调用;

  2、方法被嵌套在一个不使用注解的父方法中调用。

  那么针对以上两个情况再进行测试,去掉使用默认数据源的方法,只在父方法中嵌套一个进行调用:

  @RequestMapping("/user/age")
public String getAge(){
int age2=getAgeOfUser2();
return "other_data:"+age2;
}

  得到的结果如下所示:

  

  结果得到的还是主数据源的数据,也就是说,切换数据源的注解失效与另一个无注解的方法无关,而是因为被嵌套在一个无注解的父方法上。

  在无注解的父方法上加上切换数据源的注解,再次进行测试如下:

  @RequestMapping("/user/age")
  @DataSource(DataSourceName.SECOND)
  public String getAge(){
    int age2=getAgeOfUser2();
    return "other_data:"+age2;
  }

  得到的结果是:

  

  到这儿,基本就清楚了。

  之所以切换数据源的注解失效,是因为方法嵌套时,子方法的DataSource注解被父方法覆盖了

三、问题解决

  1、使用代理对象:

  (1)引入spring-aspects依赖包:

        <!-- spring-aspects -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aspects</artifactId>
<version>5.1.2.RELEASE</version>
</dependency>

  (2)修改入口类的@EnableAspectJAutoProxy注解为:

@EnableAspectJAutoProxy(exposeProxy = true)

  exposeProxy = true的作用是暴露当前代理对象到当前线程绑定。

  (3)修改controller层中方法的调用方式:

  AopContext.currentProxy()使用ThreadLocal保存了代理对象,所以直接把方法之间的调用方式改为代理对象之间的调用即可。

/**
* 两个方法同时执行
* @return String
*/
@RequestMapping("/user/age")
public String getAge(){
int age1=((UserController)AopContext.currentProxy()).getAgeOfUser();
int age2=((UserController)AopContext.currentProxy()).getAgeOfUser2();
return "spring_boot_demo:"+age1+";other_data:"+age2;
}

  代码如上所示,使用((UserController)AopContext.currentProxy()).getAgeOfUser()的方式,通过代理对象调用方法,所得结果为:

  

  两个数据库的结果同时获取并显示了。

  2、把DataSource注解放到service层的方法中:

  (1)修改Service层的方法,加上注解:

    @Override
public int getAgeByUsername(String username) {
return userMapper.getAgeByUsername(username);
} @Override
@DataSource(DataSourceName.SECOND)
public int getAgeByUsername2(String username) {
return userMapper.getAgeByUsername(username);
}

  (2)在controller中直接调用即可:

  /**
* 两个方法同时执行
* @return String
*/
@RequestMapping("/user/age")
public String getAge(){
int age1=userService.getAgeByUsername("springbootdemo");
int age2=userService.getAgeByUsername2("springbootdemo");
return "spring_boot_demo:"+age1+";other_data:"+age2;
}

  结果如下:

  

  

SpringBoot框架:两个方法同时调用时父方法使内部方法的DataSource注解失效的解决办法的更多相关文章

  1. springboot 使用maven 打包 报 (请使用 -source 7 或更高版本以启用 diamond 运算符) 错误解决办法

    在使用springboot maven 打包时 报如下错误 (请使用 -source 7 或更高版本以启用 diamond 运算符) pom.xml编译插件 配置如下: <plugin> ...

  2. web自动化selenium click()方法失效的解决办法

    使用Python写web-ui自动化脚本时,如果浏览器窗口比较小或者电脑屏幕比较小时, 可能会遇到页面元素的点击click()方法失效的问题,报错如下: Element <span>... ...

  3. 第二十六篇、因为自定item(nav)而使系统右滑返回手势失效的解决方法

    @interface ViewController () <uigesturerecognizerdelegate> @end@implementation ViewController ...

  4. SpringBoot 内部方法调用,事务不起作用的原因及解决办法

    在做业务开发时,遇到了一个事务不起作用的问题.大概流程是这样的,方法内部的定时任务调用了一个带事务的方法,失败后事务没有回滚.查阅资料后,问题得到解决,记录下来分享给大家. 场景 我在这里模拟一个场景 ...

  5. vue 父子组件传值以及方法调用,平行组件之间传值以及方法调用大全

    vue项目经常需要组件间的传值以及方法调用,具体场景就不说了,都知道.基本上所有的传值都可以用vuex状态管理来实现,只要在组件内监听vuex就好. vue常用的传值方式以及方法有: 1. 父值传子( ...

  6. python类的内部方法

    目录 一.绑定方法与非绑定方法 1.绑定方法 2.非绑定方法 二.property 1.什么是property? 2.为什么要用property? 3.如何使用property? 三.isinstan ...

  7. SpringBoot在Impl类中调用其它service层失败解决办法

    在AImpl.java文件中引用BImpl.java的方法,编译正常,运行到调用的地方,报空指针异常,跟踪到异常位置,发现service为空,也就是按照之前controller层通过@Autowire ...

  8. Spring 内部方法调用失效问题(AOP)

    AOP使用的是动态代理的机制,它会给类生成一个代理类,事务的相关操作都在代理类上完成.内部方式使用this调用方式时,使用的是实例调用,并没有通过代理类调用方法,所以会导致事务失效. 解决办法 方式一 ...

  9. SpringBoot框架——从SpringBoot看IoC容器初始化流程之方法分析

    目录 一.概观Spring Boot 二.Spring Boot应用初始化 2.1 初始化入口 2.2 SpringApplication的run方法 2.3 方法分析 三.容器创建与初始化 3.1 ...

随机推荐

  1. hook框架-frida使用-APP在模拟器无法打开,用钩子去除限制

    app拿soul为例子 一.环境配置 #模拟器的frida服务为86 #frida-server-12.9.8-android-x86 adb push frida-server-12.9.8-and ...

  2. 算法-heapq模块优先队列

    heapq模块, 优先队列,小顶堆,最少值放在顶部,值越小,优先级越高 heapq.heappop(heap) 从堆中弹出最小的元素,并重新调整 heapq.heappush(heap, item)新 ...

  3. rlpyt(Deep Reinforcement Learning in PyTorch)

    rlpyt: A Research Code Base for Deep Reinforcement Learning in PyTorch Github:https://github.com/ast ...

  4. 洛谷p1052过河 路径压缩+dp

    洛谷 P1052 过河 思路部分可以看这篇博客 我将在这里对其进行一些解释与补充 首先我们先看题 乍一看 这不是模板题吗 然后开开心心的敲了一个简单dp上去 #include<iostream& ...

  5. CSS动画实例:3D立方体

    CSS3支持3D转换,与3D转换有关的属性有: transform:向元素应用 2D或3D 转换. transform-origin:改变被转换元素的位置. transform-style:规定被嵌套 ...

  6. Java I/O体系从原理到应用(非原创)

    基础概念 在介绍I/O原理之前,先重温几个基础概念: 1 操作系统与内核 操作系统:管理计算机硬件与软件资源的系统软件内核:操作系统的核心软件,负责管理系统的进程.内存.设备驱动程序.文件和网络系统等 ...

  7. e3mall商城的归纳总结5之修改商品分类、e3mall—content的搭建

    说在前面的话 本节基本上没有用到新的知识点.主要还是对数据库的增删改查以及创建了一个新的内容模块. 新增商品分类 由于easyUI的Tree需要三个字段(Id.state.text), [{ &quo ...

  8. 热更新 && 增量更新

    Unity中SLua.Tolua.XLua和ILRuntime效率评测 http://blog.csdn.net/u011467512/article/details/72716376 如何阅读lua ...

  9. 万字长文,以代码的思想去详细讲解yolov3算法的实现原理和训练过程,Visdrone数据集实战训练

    以代码的思想去详细讲解yolov3算法的实现原理和训练过程,并教使用visdrone2019数据集和自己制作数据集两种方式去训练自己的pytorch搭建的yolov3模型,吐血整理万字长文,纯属干货 ...

  10. 哪些方法可以绕过PowerShell Execution Policy?

    哪些方法可以绕过PowerShell Execution Policy? 转: https://blog.csdn.net/qq_27446553/article/details/50577296