spring aop 初体验

  aop全称Aspect Oriented Programming,意为面向切面编程,aop也不是什么新鲜的技术,其底层也是通过动态代理实现,目的是增强原代码功能并完成解耦。为了达到这样的目的,就需要对原来的对象织入代码,所以我们需要通过动态代理技术,生成一个新的代理类,来完成功能的增强。这样,我们就可以把切面部分的代码与原代码分开编写,在运行代码的逻辑时候,由生成的代理类来执行。在spring中,事务、日志都可以看作一个切面,可以这样说,只要有共同特征的类或者方法,都可以称之为切面。

  我们再回顾一下上一章关于动态数据源切换的例子,我们可以把需要切换数据源的操作看作是一个切面,我们先看看spring aop如何实现的(毕竟我们大部分情况下都在spring下进行开发):

  我们定义一个需要切换数据源的注解:

  

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface DsAnnotation {
}

  定义一个切面类:

  

@Component
@Aspect
public class DataSourceAsepect {


    @Autowired
    private DynamicDataSourceConfig config;

    @Pointcut("@annotation(com.study.dyndatasource.annotation.DsAnnotation)")
    public void pointCut(){

    }

    @Around(value = "pointCut()") public Object switchDataSource(ProceedingJoinPoint point) throws Throwable { System.out.println("切换数据源"); // config.router(createTime); MethodSignature signature = (MethodSignature) point.getSignature(); Method method = signature.getMethod(); final Object[] args = point.getArgs();//参数 for(int i=0;i<args.length;i++){ // System.out.println(args); Class clazz = args[0].getClass(); Field[] fields = clazz.getDeclaredFields(); for(Field field:fields){ if(field.getName().equalsIgnoreCase("createTime")){ //这一段需要做约定,必须有数据类型为Long的名为createTime的属性 field.setAccessible(true); config.router(getOddOrEven((Long) field.get(args[i]))); } } } return point.proceed(); } /** * 判断是奇数还是偶数 * 奇数返回1 * 偶数返回2 * @param x * @return */ private int getOddOrEven(Long x){ if(x % 2 == 0){ return 2; } return 1; } }

再回过来看OrderServiceImpl类,我们在createOrder()方法上增加@DsAnnotation注解

@Service("orderService")
public class OrderServiceImpl implements OrderService {
    @Autowired
    private OrderDao orderDao;
    @Override
    @DsAnnotation  //这个注解用来触发aop,切换数据源
    public int createOrder(OrderEntity order) {
        System.out.println("OrderService调用orderDao创建订单");
        return orderDao.insert(order); } }

 运行结果:


  

OrderEntity(id=1, orderInfo={订单1}, createTime=1587818744477)
切换数据源
动态分配数据源名称:mysql_1
打印数据源信息DataSourceProperties(userName=db01, password=123456, driverClassName=com.mysql.jdbc.Driver, url=jdbc:mysql://192.168.0.104:3306/db01?Unicode=true&characterEncoding=UTF-8&autoReconnect=true&useSSL=false)
OrderService调用orderDao创建订单
创建订单成功
OrderEntity(id=1, orderInfo={订单2}, createTime=1587818744478)
切换数据源
动态分配数据源名称:mysql_2
打印数据源信息DataSourceProperties(userName=db02, password=123456, driverClassName=com.mysql.jdbc.Driver, url=jdbc:mysql://192.168.0.104:3306/db02?Unicode=true&characterEncoding=UTF-8&autoReconnect=true&useSSL=false)
OrderService调用orderDao创建订单
创建订单成功


   这样的话只需要在方法上增加DsAnnotation注解,并且约定参数的实体类有Long createTime,那就可以根据createTime来进行数据源的动态切换来达到分库的目的。

猜你喜欢

转载自www.cnblogs.com/chalice/p/12782500.html