千家信息网

spring中怎么通过注解切换多数据源

发表于:2024-09-22 作者:千家信息网编辑
千家信息网最后更新 2024年09月22日,spring中怎么通过注解切换多数据源,针对这个问题,这篇文章详细介绍了相对应的分析和解答,希望可以帮助更多想解决这个问题的小伙伴找到更简单易行的方法。第一步,配置数据源
千家信息网最后更新 2024年09月22日spring中怎么通过注解切换多数据源

spring中怎么通过注解切换多数据源,针对这个问题,这篇文章详细介绍了相对应的分析和解答,希望可以帮助更多想解决这个问题的小伙伴找到更简单易行的方法。

第一步,配置数据源

                                                       

第二步,定义用来切库的注解,和枚举类

@Target({ElementType.METHOD})@Retention(RetentionPolicy.RUNTIME)public @interface Dataswitch {    Datatype value() default Datatype.master;}public enum Datatype {    master("masterDataSource"),slave("slaveDataSource");    private String value;    Datatype(String name){        this.value = name;    }     public String getValue() {        return value;    }     public void setValue(String value) {        this.value = value;    }}

第三步,定义一个当前线程的变量的工具类,用于设置对应的数据源名称

public  class DynamicDataSourceHolder {    private static final ThreadLocal threadLocal = new ThreadLocal();     public static String getThreadLocal() {        return threadLocal.get();    }     public static void setThreadLocal(String name) {        threadLocal.set(name);    }    public static void clear(){        threadLocal.remove();    }}

第四步,创建AbstactRoutingDataSource的子类,重写determineCurrentLockupKey方法

public class DynamicDataSource extends AbstractRoutingDataSource{    protected Object determineCurrentLookupKey() {        System.out.println(DynamicDataSourceHolder.getThreadLocal());        return DynamicDataSourceHolder.getThreadLocal();    }}

第五步,将多数据源配置到用我们创建的DynamicDataSource

                                       

第六步,配置切面,在操作数据库方法之前,获取注解配置的数据源名称,返回

@Component@Aspect@Order(0)public class DataSourceAspect {    @Pointcut("execution (* xin.youhuila.sorceswitch.service..*(..))")    public void aspect(){     }    @Before("aspect()")    public void before(JoinPoint joinPoint){        Class clazz = joinPoint.getTarget().getClass();        Method[] method = clazz.getMethods();        Dataswitch dataswitch = null;        boolean is = false;        for(Method m:method){//此处最好改成通过签名获取调用方法是否含有注解,而不是遍历每个方法,可参考http://www.gitout.cn/?p=2398            if(m.isAnnotationPresent(Dataswitch.class)){                dataswitch = m.getAnnotation(Dataswitch.class);                DynamicDataSourceHolder.setThreadLocal(dataswitch.value().getValue());                is = true;            }        }        if(!is){            DynamicDataSourceHolder.setThreadLocal(Datatype.master.getValue());        }    }    @After("aspect()")    public void after(){        DynamicDataSourceHolder.clear();    }}

第七步,使用

@Servicepublic class DemoService {    @Autowired    DemoMapper demoMapper;    @Dataswitch(Datatype.master)    public void select(){        List d = demoMapper.select();        for(Demo demo:d){            System.out.println(demo);        }    }}

--------------------------------http://www.gitout.cn/?p=2398文章实现-----------------------

/** * 数据源切面 */@Aspect@Componentpublic class DynamicDataSourceAspect {                @Pointcut("@annotation(com...datasource.DynamicDataSourceAnnotation)")         public void pointCut() {        }                @Before("pointCut()")        public void testBefore(JoinPoint point) {                // 获得当前访问的class                Class className = point.getTarget().getClass();                DynamicDataSourceAnnotation dataSourceAnnotation = className.getAnnotation(DynamicDataSourceAnnotation.class);                String dataSource = DataSourceConst.DB_ACTIVITY;                // 优先级: 方法 > 类  > DB_ACTIVITY                if(dataSourceAnnotation != null) {                        dataSource = dataSourceAnnotation.dataSource();                }                String methodName = point.getSignature().getName();                // 得到方法的参数的类型                Class[] argClass = ((MethodSignature) point.getSignature()).getParameterTypes();                try {                        Method method = className.getMethod(methodName, argClass);                        if (method.isAnnotationPresent(DynamicDataSourceAnnotation.class)) {                                DynamicDataSourceAnnotation annotation = method.getAnnotation(DynamicDataSourceAnnotation.class);                                dataSource = annotation.dataSource();                        }                } catch (Exception e) {                        e.printStackTrace();                }                DataSourceContextHolder.setDataSourceType(dataSource);        }        @After("pointCut()")        public void testAfter(JoinPoint point) {                // 获得当前访问的class                Class className = point.getTarget().getClass();                DynamicDataSourceAnnotation dataSourceAnnotation = className.getAnnotation(DynamicDataSourceAnnotation.class);                if (dataSourceAnnotation != null) {                        // 获得访问的方法名                        String methodName = point.getSignature().getName();                        // 得到方法的参数的类型                        Class[] argClass = ((MethodSignature) point.getSignature()).getParameterTypes();                        String dataSource = DataSourceConst.DB_ACTIVITY;                        try {                                Method method = className.getMethod(methodName, argClass);                                if (method.isAnnotationPresent(DynamicDataSourceAnnotation.class)) {                                        DynamicDataSourceAnnotation annotation = method.getAnnotation(DynamicDataSourceAnnotation.class);                                        dataSource = annotation.dataSource();                                }                        } catch (Exception e) {                                e.printStackTrace();                        }                        if (dataSource != null && !DataSourceConst.DB_ACTIVITY.equals(dataSource)) {                                DataSourceContextHolder.clearDataSourceType();                        }                }        }}

关于spring中怎么通过注解切换多数据源问题的解答就分享到这里了,希望以上内容可以对大家有一定的帮助,如果你还有很多疑惑没有解开,可以关注行业资讯频道了解更多相关知识。

0