AOP实现
说明 | jump |
---|---|
数据源注解 | DataSource.java |
AOP实现 | DataSourceAspect.java |
数据源常量 | DataSourceNames.java |
动态数据源 | DynamicDataSource.java |
动态数据源config | DynamicDataSourceConfig.java |
DataSource.java
package com.saicmotor.carapp.service.bvalue.manage.common.config.datasource;import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface DataSource {String value() default "";
}
DataSourceAspect.java
package com.saicmotor.carapp.service.bvalue.manage.common.config.datasource;import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.core.Ordered;
import org.springframework.stereotype.Component;import java.lang.reflect.Method;@Component
@Aspect
@Slf4j
public class DataSourceAspect implements Ordered {@Pointcut("@annotation(DataSource)")public void dataSourcePointCut() {}@Around("dataSourcePointCut()")public Object around(ProceedingJoinPoint point) throws Throwable {MethodSignature signature = (MethodSignature) point.getSignature();Method method = signature.getMethod();DataSource ds = method.getAnnotation(DataSource.class);if(ds == null){DynamicDataSource.setDataSource(DataSourceNames.FIRST);log.debug("set datasource is " + DataSourceNames.FIRST);}else {DynamicDataSource.setDataSource(ds.value());log.debug("set datasource is " + ds.value());}try {return point.proceed();} finally {DynamicDataSource.clearDataSource();log.debug("clean datasource");}}@Overridepublic int getOrder() {return 1;}}
DataSourceNames.java
package com.saicmotor.carapp.service.bvalue.manage.common.config.datasource;public interface DataSourceNames {String FIRST = "first";String SECOND = "second";
}
DynamicDataSource.java
package com.saicmotor.carapp.service.bvalue.manage.common.config.datasource;import com.alibaba.druid.pool.DruidDataSource;
import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;import java.util.Map;public class DynamicDataSource extends AbstractRoutingDataSource {private static final ThreadLocal<String> contextHolder = new ThreadLocal<>();public DynamicDataSource(DruidDataSource defaultTargetDataSource, Map<Object, Object> targetDataSources) {super.setDefaultTargetDataSource(defaultTargetDataSource);super.setTargetDataSources(targetDataSources);super.afterPropertiesSet();}@Overrideprotected Object determineCurrentLookupKey() {return getDataSource();}public static void setDataSource(String dataSource) {contextHolder.set(dataSource);}public static String getDataSource() {return contextHolder.get();}public static void clearDataSource() {contextHolder.remove();}
}
DynamicDataSourceConfig.java
package com.saicmotor.carapp.service.bvalue.manage.common.config.datasource;import com.alibaba.druid.pool.DruidDataSource;
import com.alibaba.druid.spring.boot.autoconfigure.DruidDataSourceBuilder;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;import java.util.HashMap;
import java.util.Map;@Configuration
public class DynamicDataSourceConfig {@Bean@ConfigurationProperties("spring.datasource.first")public DruidDataSource firstDataSource(){return DruidDataSourceBuilder.create().build();}@Bean@ConfigurationProperties("spring.datasource.second")public DruidDataSource secondDataSource(){return DruidDataSourceBuilder.create().build();}@Bean@Primarypublic DynamicDataSource dataSource(DruidDataSource firstDataSource, DruidDataSource secondDataSource) {Map<Object, Object> targetDataSources = new HashMap<>();targetDataSources.put(DataSourceNames.FIRST, firstDataSource);targetDataSources.put(DataSourceNames.SECOND, secondDataSource);return new DynamicDataSource(firstDataSource, targetDataSources);}}