spring学习笔记之AOP与transaction

1. 什么是AOP(Aspect oriented programming)

1) 核心概念

  1. aspect:如果说class是OOP(Object Oriented Programming)中的一等公民,那么aspect就是AOP中的一等公民。aspect用于cross-cutting concern的模块化。
  2. cross-cutting concern: 个人理解,AOP是为cross-cutting concern而生的,对于这个相对抽象的概念,用举例来解释的话,就是transaction management了。
  3. join point: 程序执行中的某一个点,用于在该点插入advice。
  4. advice: aspect在某个join point进行的操作,有以下类型:around,before,after。通常advice又称为interception。
  5. pointcut: 用于匹配找到某个join point的条件表达式。
  6. AOP proxy: 用于实现aspect。

2. spring declarative transaction management

1)transaction is not only about DB, but also domain service.

transaction的概念,个人理解应该是始于database,为了保证数据库操作的原子性,但随着后来的发展,transaction的概念不仅限于数据库操作,更重要的用于service层面,用于保证service的原子性。比如银行卡取款,这可以理解为银行提供的一项service,该service的内部实现包括很多动作,比如在你的账户中扣除相应金额,以及将那些输出那些钱给你;可以想象,如果这样的service没有transaction的保护,就会出现问题了。相似的,很多service都需要包含这样的transaction特性。比如在我工作的项目中,就有domain service会用transaction包装起来。

2) spring declarative transaction management用起来貌似很简单。

spring的官方文档中说,spring提供的declarative transaction management很容易实现,只需要将那个class用@transactional annotation进行标注。同时在我们项目中,有一个domain service需要标记为transaction,因此我们就用@transaction标注该service。但是当我们运行相关测试的时候,问题出现了,error message显示没有interface与给domain service对应。这又是怎么回事呢?

pubic class CustomerService {
   @Transactional
  public Customer getCustomer(Integer customerId) {
         ..........
  }  
 }

3)上面问题的奥妙在于AOP proxy。

针对上面问题,我们去查spring declarative transaction management的实现,发现原来spring transaction的实现依托于AOP proxy。spring中的AOP proxy包括JDK dynamic proxy和CGLIB proxy,其中默认使用JDK dynamic proxy。而JDK dynamic proxy只支持interface中提供方法的proxy而不支持具体的class,CGLIB则同时支持具体class中方法的proxy,但由于面向接口本来就是oop中推荐的方式,因此推荐令domain service实现接口,以实现对其进行transaction管理。然后我们的code就修改成了这个样子,错误就消失了:

pubic class DefaultCustomerService implements CustomerService{
   @Override
   @Transactional
  public Customer getCustomer(Integer customerId) {
         ..........
  }  
 }

4)AOP proxy是如何影响方法调用的。

在学习AOP proxy的同时,也解决了之前的另一个疑问。在尝试debug被spring transaction管理的domain service时,如果尝试dubug into该方法就会进入invoke方法。其实invoke方法也是由spring AOP提供的。

下图是POJO中提供的方法的调用:

从代码的角度来理解:

public class Main {

   public static void main(String[] args) {
   
      Pojo pojo = new SimplePojo();
      
      // this is a direct method call on the ‘pojo‘ reference
      pojo.foo();
   }
}

 

下图是AOP proxy情形下的方法调用:

从代码的角度来理解:

public class Main {

   public static void main(String[] args) {
   
      ProxyFactory factory = new ProxyFactory(new SimplePojo());
      factory.addInterface(Pojo.class);
      factory.addAdvice(new RetryAdvice());

      Pojo pojo = (Pojo) factory.getProxy();
      
      // this is a method call on the proxy!
      pojo.foo();
   }
}

关于transaction还有很多话可以讲,以后再讲吧:)

郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。