举例讲解Java的Spring框架中AOP程序设计方式的使用

 更新时间:2016年04月27日 16:34:00   作者:HotStrong  
这篇文章主要介绍了Java的Spring框架中AOP程序设计方式的使用讲解,文中举的AOP下抛出异常的例子非常实用,需要的朋友可以参考下

1、什么是AOP

AOP是Aspect Oriented Programming的缩写,意思是面向方面编程,AOP实际是GoF设计模式的延续。

2、关于Spring AOP的一些术语:
 A、切面(Aspect):在Spring AOP中,切面可以使用通用类或者在普通类中以@Aspect 注解(@AspectJ风格)来实现
B、连接点(Joinpoint):在Spring AOP中一个连接点代表一个方法的执行
C、通知(Advice):在切面的某个特定的连接点(Joinpoint)上执行的动作。通知有各种类型,其中包括"around"、"before”和"after"等通知。许多AOP框架,包括Spring,都是以拦截器做通知模型, 并维护一个以连接点为中心的拦截器链
D、切入点(Pointcut):定义出一个或一组方法,当执行这些方法时可产生通知,Spring缺省使用AspectJ切入点语法。

3、通知类型
A、前置通知(@Before):在某连接点(join point)之前执行的通知,但这个通知不能阻止连接点前的执行(除非它抛出一个异常)
B、返回后通知(@AfterReturning):在某连接点(join point)正常完成后执行的通知:例如,一个方法没有抛出任何异常,正常返回
C、抛出异常后通知(@AfterThrowing):方法抛出异常退出时执行的通知
D、后通知(@After):当某连接点退出的时候执行的通知(不论是正常返回还是异常退出)
E、环绕通知(@Around):包围一个连接点(join point)的通知,如方法调用。这是最强大的一种通知类型,环绕通知可以在方法调用前后完成自定义的行为,它也会选择是否继续执行连接点或直接返回它们自己的返回值或抛出异常来结束执行
 
4、@AspectJ风格的AOP配置

Spring AOP配置有两种风格:
A、XML风格 = 采用声明形式实现Spring AOP
B、AspectJ风格 = 采用注解形式实现Spring AOP

5、实例

切面类TestAspect

package com.spring.aop; 
/** 
 * 切面 
 */ 
public class TestAspect { 
 
  public void doAfter(JoinPoint jp) { 
    System.out.println("log Ending method: " 
        + jp.getTarget().getClass().getName() + "." 
        + jp.getSignature().getName()); 
  } 
 
  public Object doAround(ProceedingJoinPoint pjp) throws Throwable { 
    long time = System.currentTimeMillis(); 
    Object retVal = pjp.proceed(); 
    time = System.currentTimeMillis() - time; 
    System.out.println("process time: " + time + " ms"); 
    return retVal; 
  } 
 
  public void doBefore(JoinPoint jp) { 
    System.out.println("log Begining method: " 
        + jp.getTarget().getClass().getName() + "." 
        + jp.getSignature().getName()); 
  } 
 
  public void doThrowing(JoinPoint jp, Throwable ex) { 
    System.out.println("method " + jp.getTarget().getClass().getName() 
        + "." + jp.getSignature().getName() + " throw exception"); 
    System.out.println(ex.getMessage()); 
  } 
 
  private void sendEx(String ex) { 
    //TODO 发送短信或邮件提醒 
  } 
}  

package com.spring.service; 
/** 
 * 接口A 
 */ 
public interface AService { 
   
  public void fooA(String _msg); 
 
  public void barA(); 
} 
package com.spring.service; 
/** 
 *接口A的实现类 
 */ 
public class AServiceImpl implements AService { 
 
  public void barA() { 
    System.out.println("AServiceImpl.barA()"); 
  } 
 
  public void fooA(String _msg) { 
    System.out.println("AServiceImpl.fooA(msg:"+_msg+")"); 
  } 
} 
package com.spring.service; 
 
/** 
 *  Service类B 
 */ 
public class BServiceImpl { 
 
  public void barB(String _msg, int _type) { 
    System.out.println("BServiceImpl.barB(msg:"+_msg+" type:"+_type+")"); 
    if(_type == 1) 
      throw new IllegalArgumentException("测试异常"); 
  } 
 
  public void fooB() { 
    System.out.println("BServiceImpl.fooB()"); 
  } 
 
} 

ApplicationContext

<?xml version="1.0" encoding="UTF-8"?> 
<beans xmlns="http://www.springframework.org/schema/beans" 
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
  xmlns:aop="http://www.springframework.org/schema/aop" 
  xsi:schemaLocation=" 
      http://www.springframework.org/schema/beans 
      http://www.springframework.org/schema/beans/spring-beans-2.0.xsd 
      http://www.springframework.org/schema/aop 
      http://www.springframework.org/schema/aop/spring-aop-2.5.xsd" 
  default-autowire="autodetect"> 
  <aop:config> 
    <aop:aspect id="TestAspect" ref="aspectBean"> 
      <!--配置com.spring.service包下所有类或接口的所有方法--> 
      <aop:pointcut id="businessService" 
        expression="execution(* com.spring.service.*.*(..))" /> 
      <aop:before pointcut-ref="businessService" method="doBefore"/> 
      <aop:after pointcut-ref="businessService" method="doAfter"/> 
      <aop:around pointcut-ref="businessService" method="doAround"/> 
      <aop:after-throwing pointcut-ref="businessService" method="doThrowing" throwing="ex"/> 
    </aop:aspect> 
  </aop:config> 
   
  <bean id="aspectBean" class="com.spring.aop.TestAspect" /> 
  <bean id="aService" class="com.spring.service.AServiceImpl"></bean> 
  <bean id="bService" class="com.spring.service.BServiceImpl"></bean> 
 
</beans> 

 测试类AOPTest

public class AOPTest extends AbstractDependencyInjectionSpringContextTests { 
   
  private AService aService; 
   
  private BServiceImpl bService; 
   
  protected String[] getConfigLocations() { 
    String[] configs = new String[] { "/applicationContext.xml"}; 
    return configs; 
  } 
   
   
  /** 
   * 测试正常调用 
   */ 
  public void testCall() 
  { 
    System.out.println("SpringTest JUnit test"); 
    aService.fooA("JUnit test fooA"); 
    aService.barA(); 
    bService.fooB(); 
    bService.barB("JUnit test barB",0); 
  } 
   
  /** 
   * 测试After-Throwing 
   */ 
  public void testThrow() 
  { 
    try { 
      bService.barB("JUnit call barB",1); 
    } catch (IllegalArgumentException e) { 
       
    } 
  } 
   
  public void setAService(AService service) { 
    aService = service; 
  } 
   
  public void setBService(BServiceImpl service) { 
    bService = service; 
  } 
} 

 
运行结果如下:

log Begining method: com.spring.service.AServiceImpl.fooA 
AServiceImpl.fooA(msg:JUnit test fooA) 
log Ending method: com.spring.service.AServiceImpl.fooA 
process time: 0 ms 
log Begining method: com.spring.service.AServiceImpl.barA 
AServiceImpl.barA() 
log Ending method: com.spring.service.AServiceImpl.barA 
process time: 0 ms 
log Begining method: com.spring.service.BServiceImpl.fooB 
BServiceImpl.fooB() 
log Ending method: com.spring.service.BServiceImpl.fooB 
process time: 0 ms 
log Begining method: com.spring.service.BServiceImpl.barB 
BServiceImpl.barB(msg:JUnit test barB type:0) 
log Ending method: com.spring.service.BServiceImpl.barB 
process time: 0 ms 
 
log Begining method: com.spring.service.BServiceImpl.barB 
BServiceImpl.barB(msg:JUnit call barB type:1) 
log Ending method: com.spring.service.BServiceImpl.barB 
method com.spring.service.BServiceImpl.barB throw exception 
测试异常 

相关文章

  • Java线程优先级和守护线程原理解析

    Java线程优先级和守护线程原理解析

    这篇文章主要介绍了Java线程优先级和守护线程原理解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-03-03
  • Java匿名类和匿名函数的概念和写法

    Java匿名类和匿名函数的概念和写法

    匿名函数写法和匿名类写法的前提必须基于函数式接口匿名函数写法和匿名类写法其本质是同一个东西,只是简化写法不同使用Lambda表达式简写匿名函数时,可以同时省略实现类名、函数名,这篇文章主要介绍了Java匿名类和匿名函数的概念和写法,需要的朋友可以参考下
    2023-06-06
  • Mapstruct @Mapper @Mapping 使用小结

    Mapstruct @Mapper @Mapping 使用小结

    这篇文章主要介绍了Mapstruct @Mapper @Mapping使用小结,他们用于各个对象实体间的相互转换,例如数据库底层实体转为页面对象,Model 转为 DTO, DTO 转为其他中间对象, VO 等等,相关转换代码为编译时自动产生的新文件和代码,需要的朋友可以参考下
    2023-09-09
  • Spring Boot命令行启动添加参数的三种方式

    Spring Boot命令行启动添加参数的三种方式

    在命令行中,常见的参数可以分为三类:选项参数、非选项参数和系统参数,本文就来介绍一下Spring Boot命令行三种参数形式,感兴趣的可以了解一下
    2023-09-09
  • Java中数组和List的互相转换问题小结

    Java中数组和List的互相转换问题小结

    这篇文章主要介绍了Java中数组和List的互相转换问题小结,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2024-03-03
  • 深入了解java NIO之Selector(选择器)

    深入了解java NIO之Selector(选择器)

    这篇文章主要介绍了java NIO之Selector(选择器)的相关资料,文中讲解非常详细,实例代码帮助大家更好的理解和学习,感兴趣的朋友可以了解下
    2020-07-07
  • java蓝桥杯试题

    java蓝桥杯试题

    这篇文章主要介绍了java蓝桥杯试题,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-02-02
  • MyBatis多数据源的两种配置方式

    MyBatis多数据源的两种配置方式

    这篇文章主要给大家介绍了关于MyBatis多数据源的两种配置方式,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2018-12-12
  • Java使用entrySet方法获取Map集合中的元素

    Java使用entrySet方法获取Map集合中的元素

    这篇文章主要为大家详细介绍了Java使用entrySet方法获取Map集合中的元素,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2018-08-08
  • java构建OAuth2授权服务器

    java构建OAuth2授权服务器

    本文主要介绍了java构建OAuth2授权服务器,文中通过示例代码介绍的非常详细,需要的朋友们下面随着小编来一起学习学习吧
    2021-07-07

最新评论