美文网首页Sping 专题coder
spring下多数据源的切换使用(二)使用注解方式

spring下多数据源的切换使用(二)使用注解方式

作者: S拒绝拖延 | 来源:发表于2019-07-08 11:01 被阅读0次

    一、定义一个名为DataSource的注解

    @Target({ TYPE, METHOD })
    @Retention(RUNTIME)
     public @interface DataSource {
        String value();
     }
    

    二、定义AOP切面以便拦截所有带有注解@DataSource的方法,取出注解的值作为数据源标识放到DynamicDataSourceHolder的线程变量中:

    public class DataSourceAspect {
    
        /**
         * 拦截目标方法,获取由@DataSource指定的数据源标识,设置到线程存储中以便切换数据源
         * 
         * @param point
         * @throws Exception
         */
        public void intercept(JoinPoint point) throws Exception {
            Class<?> target = point.getTarget().getClass();
            MethodSignature signature = (MethodSignature) point.getSignature();
            // 默认使用目标类型的注解,如果没有则使用其实现接口的注解
            for (Class<?> clazz : target.getInterfaces()) {
                resolveDataSource(clazz, signature.getMethod());
            }
            resolveDataSource(target, signature.getMethod());
        }
    
        /**
         * 提取目标对象方法注解和类型注解中的数据源标识
         * 
         * @param clazz
         * @param method
         */
        private void resolveDataSource(Class<?> clazz, Method method) {
            try {
                Class<?>[] types = method.getParameterTypes();
                // 默认使用类型注解
                if (clazz.isAnnotationPresent(DataSource.class)) {
                    DataSource source = clazz.getAnnotation(DataSource.class);
                    DynamicDataSourceHolder.setDataSource(source.value());
                }
                // 方法注解可以覆盖类型注解
                Method m = clazz.getMethod(method.getName(), types);
                if (m != null && m.isAnnotationPresent(DataSource.class)) {
                    DataSource source = m.getAnnotation(DataSource.class);
                    DynamicDataSourceHolder.setDataSource(source.value());
                }
            } catch (Exception e) {
                System.out.println(clazz + ":" + e.getMessage());
            }
        }
    }
    

    三、在spring配置文件中配置拦截规则,比如拦截service层或者dao层的所有方法

    <bean id="dataSourceAspect" class="com.test.context.datasource.DataSourceAspect" />
        <aop:config>
            <aop:aspect ref="dataSourceAspect">
                <!-- 拦截所有service方法 -->
                <aop:pointcut id="dataSourcePointcut" expression="execution(* com.test.*.dao.*.*(..))"/>
                <aop:before pointcut-ref="dataSourcePointcut" method="intercept" />
            </aop:aspect>
        </aop:config>
    </bean>
    

    四、直接在类或者方法上使用注解@DataSource来指定数据源

    @Service
    // 默认DataServiceImpl下的所有方法均访问数据源1
    @DataSource("dataSource1")
    public class DataServiceImpl implements DataService {
        @Autowired
        private DataMapper dataMapper;
        @Override
        public List<Map<String, Object>> getList1() {
            // 不指定,则默认使用数据源1
            return dataMapper.getList1();
        }
        @Override
        // 覆盖类上指定的,使用数据源2
        @DataSource("dataSource2")
        public List<Map<String, Object>> getList2() {
            return dataMapper.getList2();
        }
    }
    

    相关文章

      网友评论

        本文标题:spring下多数据源的切换使用(二)使用注解方式

        本文链接:https://www.haomeiwen.com/subject/jttohctx.html