首页 > 编程语言 > 详细

spring aop 初体验

时间:2020-05-17 14:07:11      阅读:47      评论:0      收藏:0      [点我收藏+]

  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来进行数据源的动态切换来达到分库的目的。

 

spring aop 初体验

原文:https://www.cnblogs.com/chalice/p/12782500.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!