【0 -> Spring】AOP 学习笔记 (一)

AOP

为什么要实现AOP

  • 实现代码的过程中,通常只关注业务。而实现业务中不可避免的会需要关注到一些非业务逻辑层面。例如对业务逻辑代码的执行时间的记录,对于业务逻辑代码的日志记录,对业务逻辑代码的异常处理安全验证。归类上述这些业务逻辑会发现。这些逻辑与要实现的业务逻辑是完全正交的,即X,Y轴,互不影响,但是共存。我们称对这类业务实现的编程为AOP(Aspect Oriented Programming)。

AOP术语

  • 2.1 Joint Point
    程序运行过程中能够进行插入切面操作的切入点。例如方法调用、异常抛出或字段修改等,在Spring AOP中只能是方法。在实际用的时候,这个具体的代码体现不多。
  • 2.2 Pointcut
    描述一个通知将被切入的一系列连接点的集合,即代码片段具体切入到哪些类、哪些方法。切入点规定了哪些连接点可以执行哪些植入代码。
  • 2.3 Advice
    切入到类指定方法或者指定位置的代码片段,即需要增加的功能代码。多数AOP框架,包括Spring将构建成Interceptor,在切入点上,框架维护了一系列的interceptor。
  • 2.4 Aspect
    AOP中的切面等同于OOP中的类(class),由通知(advice)和切入点(pointcut)组成,其中通知(advice)和切入点(pointcut)既可以是1对1的关系,也可以是1对多的关系。
  • 2.5 Before advice
    在切入点代码之前执行的代码。
  • 2.6 After returning advice
    在切入点代码正常执行完后执行的代码。
  • 2.7 After throwing advice
    在切入点代码报错之后执行的代码。
  • 2.8 After(finally) advice
    在切入点代码执行完后执行的代码,不管切入点代码执行的结果(normal or exceptional return.)
  • 2.9 Around Advice
    在切入点代码执行前后都会执行的代码。

轻量级 AOP

  • 从此开始,结合自己网上学习刘大大(刘欣 - 码农翻身作者)的lite-spring课程,写下学习笔记。
    一步步地实现一个轻量级的AOP,采用的是Test-Driven的开发模式。这里只实现xml形式的aop。
1. Pointcut 详解
  • 首先最简单的,我们要对一个类的方法动态的植入代码,需要我们先判断什么样的类满足我们的要求。我们下列的xml可以看出对简单的一个pointcut的定义。Pointcut的功能就是简单的表述一系列可被植入代码的method的切入点集合。将它抽象成一个类,Assuming,这个类应该是可以去判断一个method是否满足被植入代码。
<aop:pointcut id="placeOrder" 
expression="execution(* org.litespring.service.v5.*.placeOrder(..))" />
  • Spring AOP中使用了一个Pointcut接口表示上述代码,Pointcut接口返回一个MethodMatcher接口对象,MethodMatcher接口提供matches方法去比对传入的Method参数是否和表达式匹配。
  • 这里写图片描述
    这里写图片描述
@Test
    public void testPointcut() throws Exception{

        String expression = "execution(* org.litespring.service.v5.*.placeOrder(..))";

        AspectJExpressionPointcut pc = new AspectJExpressionPointcut();
        pc.setExpression(expression);

        MethodMatcher mm = pc.getMethodMatcher();

        {
            Class<?> targetClass = PetStoreService.class;

            Method method1 = targetClass.getMethod("placeOrder");
            Assert.assertTrue(mm.matches(method1));

            Method method2 = targetClass.getMethod("getAccountDao");
            Assert.assertFalse(mm.matches(method2));
        }

        {
            Class<?> targetClass = org.litespring.service.v4.PetStoreService.class;

            Method method = targetClass.getMethod("getAccountDao");
            Assert.assertFalse(mm.matches(method));
        }

    }
  • 上面的unit测试,AspectJExpressionPointcut其实就是Pointcut,它也实现了MethodMatcher。它set了expression,内部得到一个PointExpression,通过它来检测是否和目标的method是否匹配。
2. 定位植入Method 详解
<bean id="tx" class="org.litespring.tx.TransactionManager" />

<aop:config>

  <aop:aspect ref="tx">

    <aop:pointcut id="placeOrder“  expression="……" />

    <aop:before pointcut-ref="placeOrder" method="start" />

  </aop:aspect>

</aop:config>
  • AspectJExpressionPointcut是确定method是否match。确定好match的方法之后,接下来就需要通过xml确定植入需要用的method。如上,通过Bean的名称“tx”和“start”定位到这个Method,然后通过反射调用。Spring AOP使用了MethodLoatingFactor定位method。
@Test
    public void testGetMethod() throws Exception{
        DefaultBeanFactory beanFactory = new DefaultBeanFactory();
        XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(beanFactory);
        Resource resource = new ClassPathResource("petstore-v5.xml");
        reader.loadBeanDefinition(resource);

        MethodLocatingFactory methodLocatingFactory = new MethodLocatingFactory();
        methodLocatingFactory.setTargetBeanName("tx");
        methodLocatingFactory.setMethodName("start");
        methodLocatingFactory.setBeanFactory(beanFactory);

        Method m = methodLocatingFactory.getObject();

        Assert.assertTrue(TransactionManager.class.equals(m.getDeclaringClass()));
        Assert.assertTrue(m.equals(TransactionManager.class.getMethod("start")));

    }
  • 这其实就是一个工具类,通过给定的beanName获取beanClass,然后再根据methodName,反射获得method。可以用于任何通过beanName和methodName找到对应的method。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值