欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

springboot aop整合多数据源处理

程序员文章站 2024-03-17 20:22:28
...

springboot aop整合多数据源

通过aop进行切面整理

设置默认数据源 :DataSource 这个值可以是任意名称,其实就是声明一个注解,用在方法体上进行数据源切换操作

/**
 * 〈一句话功能简述〉<br> 
 * 〈声明数据源注解〉
 *
 * @create 2020/4/13
 * @since 1.0.0
 */
@Target({ElementType.METHOD})
@Documented
@Retention(RetentionPolicy.RUNTIME)
public @interface DataSource {
    String name() default "";
}
/**
 * 〈一句话功能简述〉<br> 
 * 〈设置默认数据源〉
 *
 * @create 2020/4/13
 * @since 1.0.0
 */
public class DynamicDataSource extends AbstractRoutingDataSource {

    /**
     * 默认数据源
     */
    public static final String DEFAULT_DS = "primaryDataSource";
    /**
     * 本地线程共享对象
     */
    private static final ThreadLocal<String> THREAD_LOCAL = new ThreadLocal<>();

    public static void putDataSource(String name){
        THREAD_LOCAL.set(name);
    }
    public static String getDataSource() {
        return THREAD_LOCAL.get();
    }

    @Override
    protected Object determineCurrentLookupKey() {
        return DynamicDataSource.getDataSource();
    }
    /**
     * 清除本线程使用的数据源,使用默认数据源
     */
    public static void clear() {
        THREAD_LOCAL.remove();
    }
}

设置数据源切面

/**
 * 〈一句话功能简述〉<br> 
 * 〈数据源切面〉
 *
 * @create 2020/4/13
 * @since 1.0.0
 */
@Component
@Aspect
public class DataSourceAspect implements Ordered {
	//这里就是通过aop切到项目数据源的位置(com.xxxx.springbootstudy.config.DataSource.DataSource,这个地址根据自己地址来)
    @Pointcut("@annotation(com.xxxx.springbootstudy.config.DataSource.DataSource)")
    public void pointCut() {
    }
	
    @Before("pointCut()")
    public void annotationPointCutBefore(JoinPoint joinPoint){
        //从切面获取访问得方法
        Class<?> aClass = joinPoint.getTarget().getClass();
        //从切面获取访问方法名称
        String className = joinPoint.getSignature().getName();
        //获取方法得参数类型
        Class[] argClass = ((MethodSignature)joinPoint.getSignature()).getParameterTypes();
        //获取默认数据源
        String defaultDs = DynamicDataSource.DEFAULT_DS;
        try {
            //获得访问的方法对象
            Method  method = aClass.getMethod(className, argClass);
            /**
		     * 判断是否存在@DataSource注解(isAnnotationPresent 这个方法是通过判断b是否在a中,
		     * 指的是指定 注解是否在此元素上,这里是**method**中是否存在**@DataSource**注解)
		     */
      
            if (method.isAnnotationPresent(DataSource.class)){
            	//getAnnotation  如果存在这样的注解,则返回指定类型的元素的注解,否则返回null
                DataSource annotation = method.getAnnotation(DataSource.class);
                //获取所得数据源名称
                 defaultDs = annotation.name();
            }
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        }
        // 切换数据源
        DynamicDataSource.putDataSource(defaultDs);
    }

    /**
     * 在切面之后进行数据源的清除,使用默认数据源
     * @param joinPoint
     */
    @After("pointCut()")
    public void annotationMethodAfter(JoinPoint joinPoint){
        DynamicDataSource.clear();
    }

    /**
     * 其实就是order注解,数越大,优先级越靠后
     * @return
     */
    @Override
    public int getOrder() {
        return 1;
    }
}
/**
 * 〈一句话功能简述〉<br> 
 * 〈数据源配置〉
 *
 * @create 2020/4/13
 * @since 1.0.0
 */
@Configuration
public class DataSourceConfig {
    /**
     * 声明primaryDataSource数据源,数据源注入bean
     * @return
     */
    @Bean(name = "primaryDataSource")
    @Qualifier("primaryDataSource")
    @ConfigurationProperties(prefix = "spring.datasource.druid.ds1")
    public javax.sql.DataSource primaryDataSource(){
        return DruidDataSourceBuilder.create().build();
    }

    /**
     * secondDataSource,数据源注入bean
     * @return
     */
    @Bean(name = "secondDataSource")
    @Qualifier("secondDataSource")
    //**spring.datasource.druid.ds2**这个注意别写错了,地址和你的yml中的名称一样就行
    @ConfigurationProperties(prefix = "spring.datasource.druid.ds2")
    public javax.sql.DataSource secondDataSource(){
        return DruidDataSourceBuilder.create().build();
    }


    @Primary
    @Bean
    public DataSource dataSource(){
        DynamicDataSource dataSource=new DynamicDataSource();
        /**
         * 默认数据源
         */
        dataSource.setDefaultTargetDataSource(primaryDataSource());
        /**
         * 配置多数据源
         */
        Map map=new HashMap();
        map.put("primaryDataSource",primaryDataSource());
        map.put("secondDataSource",secondDataSource());
        dataSource.setTargetDataSources(map);
        return dataSource;
    }

    /**
     * 配置@Transactional注解事物
     * @return
     */
    @Bean
    public PlatformTransactionManager transactionManager() {
        return new DataSourceTransactionManager(dataSource());
    }
}

最后贴上项目yml配置
springboot aop整合多数据源处理
再贴上pom文件,别的大同小异,前两个切面用,后两个数据源用
springboot aop整合多数据源处理
使用方式:
springboot aop整合多数据源处理

最后: 仅供参考,有错欢迎指正,我也是看了好多博客才搞懂