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

作者:HotStrong 时间:2022-11-21 21:22:15 

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,Spring,AOP
0
投稿

猜你喜欢

  • 详解使用Spring Security OAuth 实现OAuth 2.0 授权

    2023-10-01 23:05:10
  • 零基础入门SpringMVC拦截器的配置与使用

    2023-07-17 21:59:28
  • springboot 使用自定义的aspect的示例代码

    2023-08-06 08:55:14
  • Java中FilterInputStream和FilterOutputStream的用法详解

    2023-10-02 06:47:03
  • Android中实现OkHttp上传文件到服务器并带进度

    2023-02-10 21:44:09
  • Java与kotlin详细对比

    2022-04-13 23:26:47
  • C++实现扫雷游戏示例讲解

    2022-05-03 18:49:05
  • Java InheritableThreadLocal用法详细介绍

    2023-01-27 04:30:11
  • JavaWeb简单文件上传流程的实战记录

    2023-04-02 09:14:59
  • C# 使用CancellationTokenSource取消多线程

    2023-11-15 00:31:54
  • Java调用WebService接口作测试

    2023-08-11 17:00:20
  • Java+MySQL实现学生信息管理系统源码

    2023-11-28 04:29:31
  • Android四种数据存储的应用方式

    2023-07-25 05:01:06
  • Java java.sql.Timestamp时间戳案例详解

    2023-11-10 13:50:47
  • c#模拟银行atm机示例分享

    2023-04-01 10:59:45
  • 详解jeefast和Mybatis实现二级联动的问题

    2022-11-10 05:10:15
  • SpringBoot自定义MessageConverter与内容协商管理器contentNegotiationManager详解

    2023-11-28 11:35:54
  • 一文搞懂Java ScheduledExecutorService的使用

    2022-11-22 14:23:35
  • Jackson 反序列化时实现大小写不敏感设置

    2021-11-18 06:17:18
  • Windows系统中Java调用cmd命令及执行exe程序的方法

    2021-11-27 23:00:02
  • asp之家 软件编程 m.aspxhome.com