aop+自定义注解实现数据源切换

pom.xml依赖

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.3.4.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.xt</groupId>
    <artifactId>dynamicDataSource</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>dynamicDataSource</name>
    <description>dynamicDataSource</description>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <java.version>1.8</java.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-jdbc</artifactId>
        </dependency>

        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>

        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
            <version>2.2.1</version>
        </dependency>

        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid-spring-boot-starter</artifactId>
            <version>1.2.9</version>
        </dependency>

        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <scope>runtime</scope>
        </dependency>

        <dependency>
            <groupId>log4j</groupId>
            <artifactId>log4j</artifactId>
            <version>1.2.12</version>
        </dependency>
        <dependency>
            <groupId>org.testng</groupId>
            <artifactId>testng</artifactId>
            <version>5.0.2</version>
            <scope>compile</scope>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-aop</artifactId>
        </dependency>
        <dependency>
            <groupId>org.testng</groupId>
            <artifactId>testng</artifactId>
            <version>6.10</version>
            <scope>compile</scope>
        </dependency>

    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <configuration>
                    <excludes>
                        <exclude>
                            <groupId>org.projectlombok</groupId>
                            <artifactId>lombok</artifactId>
                        </exclude>
                    </excludes>
                </configuration>
            </plugin>
        </plugins>
    </build>

</project>

application.yml配置双数据源

spring:
  datasource:
    type: com.alibaba.druid.pool.DruidDataSource
    yeb:
      url: jdbc:mysql://localhost:3306/yeb?serverTimezone=Asia/Shanghai
      username: root
      password: root
      druid:
        initial-size: 1
        min-idle: 1
        max-active: 20
        test-on-borrow: true
        driver-class-name: com.mysql.cj.jdbc.Driver
    mall:
      url: jdbc:mysql://localhost:3306/mall?serverTimezone=Asia/Shanghai
      username: root
      password: root
      druid:
        initial-size: 1
        min-idle: 1
        max-active: 20
        test-on-borrow: true
        driver-class-name: com.mysql.cj.jdbc.Driver

数据库

 

 

 

 

 

 

自定义配置类,绑定配置文件属性

DataSourceConfig

package com.xt.dynamicdatasource.config;

import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import com.alibaba.druid.spring.boot.autoconfigure.DruidDataSourceBuilder;


import javax.sql.DataSource;

@Configuration
public class DataSourceConfig {

    @Bean
    @ConfigurationProperties(prefix = "spring.datasource.yeb")
    public DataSource dataSource1(){
        //底层会自动拿到spring.datasource中的配置,创建一个DruidDataSource
       return DruidDataSourceBuilder.create().build();
    }

    @Bean
    @ConfigurationProperties(prefix = "spring.datasource.mall")
    public DataSource dataSource2(){
        //底层会自动拿到spring.datasource中的配置,创建一个DruidDataSource
        return DruidDataSourceBuilder.create().build();
    }
}

自定义数据源

DynamicDataSource

package com.xt.dynamicdatasource.config;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Primary;
import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;
import org.springframework.stereotype.Component;
import javax.sql.DataSource;
import java.util.HashMap;
import java.util.Map;

@Component
@Primary//将该Bean设置为主要注入Bean
public class DynamicDataSource extends AbstractRoutingDataSource {

    //当前使用的数据源标识
    public static ThreadLocal<String> name = new ThreadLocal<>();

    @Autowired
    DataSource dataSource1;
    @Autowired
    DataSource dataSource2;

    //返回当前数据源标识
    @Override
    protected Object determineCurrentLookupKey() {

        return name.get();
    }

    @Override
    public void afterPropertiesSet() {
        //为targetDataSources初始化所有的数据源
        Map<Object, Object> targetDataSources = new HashMap<>();
        targetDataSources.put("yeb",dataSource1);
        targetDataSources.put("mall",dataSource2);
        super.setTargetDataSources(targetDataSources);

        //为defaultTargetDataSource设置默认的数据源
        super.setDefaultTargetDataSource(dataSource1);
        super.afterPropertiesSet();
    }
}

自定义注解

SwitchDB

package com.xt.dynamicdatasource.annotation;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Target({ElementType.TYPE,ElementType.METHOD})
//保留方式
@Retention(RetentionPolicy.RUNTIME)
public @interface SwitchDB {
    String value() default "yeb"; //默认yeb数据库
}

aop切面

package com.xt.dynamicdatasource.aspect;

import com.xt.dynamicdatasource.annotation.SwitchDB;
import com.xt.dynamicdatasource.config.DynamicDataSource;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.stereotype.Component;

@Component
@Aspect
public class DynamicDataSourceAspect {
    //前置通知com.xt.dynamicdatasource.service.impl下面的所有类的注解都会进行增强
    @Before("within(com.xt.dynamicdatasource.service.impl.*) && @annotation(switchDB)")
    public void before(JoinPoint point, SwitchDB switchDB){
        String name = switchDB.value();
        DynamicDataSource.name.set(name);
        System.out.println(name);
    }
}

 

在实现类上使用@SwitchDB 注解

package com.xt.dynamicdatasource.service.impl;

import com.xt.dynamicdatasource.annotation.SwitchDB;
import com.xt.dynamicdatasource.entity.User;
import com.xt.dynamicdatasource.mapper.UserMapper;
import com.xt.dynamicdatasource.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.Map;

@Service
public class UserServiceImpl implements UserService {
    @Autowired
    UserMapper userMapper;

    @Override
    @SwitchDB("yeb")//访问yeb数据库
    public User getUsers() {
        User users = userMapper.getUsers();
        return users;
    }

    @Override
    @SwitchDB("mall")//访问mall数据库
    public Map<String, Object> getMenu() {
        Map<String, Object> menu = userMapper.getMenu();
        return menu;
    }


}

 

其他代码部分

UserController

package com.xt.dynamicdatasource.controller;

import com.xt.dynamicdatasource.annotation.SwitchDB;
import com.xt.dynamicdatasource.config.DynamicDataSource;
import com.xt.dynamicdatasource.entity.User;
import com.xt.dynamicdatasource.mapper.UserMapper;
import com.xt.dynamicdatasource.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.Map;

@RestController
public class UserController {
    @Autowired
    UserService userService;

    @GetMapping("getUser")
    public User getUser(){
        User users = userService.getUsers();
        return users;
    }

    @GetMapping("getMenu")
    public Map getMenu(){
        Map<String, Object> menu = userService.getMenu();
        return menu;
    }
}

UserService

package com.xt.dynamicdatasource.service;

import com.xt.dynamicdatasource.entity.User;
import com.xt.dynamicdatasource.mapper.UserMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.Map;


public interface UserService {

    public User getUsers();

    Map<String, Object>  getMenu();
}

UserServiceImpl

package com.xt.dynamicdatasource.service.impl;

import com.xt.dynamicdatasource.annotation.SwitchDB;
import com.xt.dynamicdatasource.entity.User;
import com.xt.dynamicdatasource.mapper.UserMapper;
import com.xt.dynamicdatasource.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.Map;

@Service
public class UserServiceImpl implements UserService {
    @Autowired
    UserMapper userMapper;

    @Override
    @SwitchDB("yeb")//访问yeb数据库
    public User getUsers() {
        User users = userMapper.getUsers();
        return users;
    }

    @Override
    @SwitchDB("mall")//访问mall数据库
    public Map<String, Object> getMenu() {
        Map<String, Object> menu = userMapper.getMenu();
        return menu;
    }


}

UserMapper

package com.xt.dynamicdatasource.mapper;

import com.xt.dynamicdatasource.entity.User;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Select;
import java.util.Map;

@Mapper
public interface UserMapper {

    @Select("select * from t_user where id = 2")
    User getUsers();

    @Select("select * from t_menu where id = 7")
    Map<String,Object> getMenu();
}

启动类DynamicDataSourceApplication

package com.xt.dynamicdatasource;

import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.EnableAspectJAutoProxy;

@SpringBootApplication
@MapperScan(basePackages = "com.xt.dynamicdatasource.mapper")
@EnableAspectJAutoProxy//启动aop
public class DynamicDataSourceApplication {

    public static void main(String[] args) {
        SpringApplication.run(DynamicDataSourceApplication.class, args);
    }

}

 

 

posted @ 2023-03-12 09:12  Mr_sven  阅读(146)  评论(0编辑  收藏  举报