springAOP中的各种通知

简介: springAOP中的各种通知

在上一篇博客中我们介绍了AOP的一些基本概念,并且在博客中的Demo我们没有使用配置文件的形式来实现,在博客的结尾我们我们也抛出了那样写的问题,在这篇博客中我们就用配置文件的方式来来介绍AOP中的五大通知。


前置通知(before):在目标方法执行之前执行


后置通知(after):在目标方执行完成后执行,如果目标方法异常,则后置通知不再执行


异常通知(After-throwing):目标方法抛出异常的时候执行  


最终通知(finally);不管目标方法是否有异常都会执行,相当于try。。catch。。finally中的finally环绕通知(round):可以控制目标方法是否执行下面就通过一个栗子来总结一下这几个通知应该如何使用.


20161231100505981.png


上面截图就是demo的基本目录结构,先来说一下jar包,其中aspectjrt.jar和aspectjweaver.jar是springAOP配置文件形式所需要的jar包,其实这和springAOP的由来有联系,因为AOP的思想最原始就是aspect技术,只不过当时开发人员不知道这个技术干什么用,导致该项技术没有什么用武之地,但是到后来spring的作者意识到这种思想的优势的使用,加以整合提出aop的思想,使这项技术到达了巅峰。cglib是代理对象形成的另一种形式。


和上一篇博客对比我们可以发现,我们不需要自己写拦截器,而是在配置文件中实现。


首先来看一下配置文件:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
     xmlns:aop="http://www.springframework.org/schema/aop"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
           http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
           http://www.springframework.org/schema/aop 
           http://www.springframework.org/schema/aop/spring-aop-2.5.xsd">
      <!-- 
          导入目标类
          导入切面
          进行aop的配置
    -->        
   <bean id="personDao" class="com.itheima11.spring.aop.xml.transaction.PersonDaoImpl"></bean>
   <bean id="transaction" class="com.itheima11.spring.aop.xml.transaction.Transaction"></bean>
  <aop:config>
  <!-- 
        切入点表达式
          符合切入点表达式的类要产生代理对象
          expression就是切入点表达式
          id 标示符
       -->
    <aop:pointcut 
      expression="execution(* com.itheima11.spring.aop.xml.transaction.PersonDaoImpl.*(..))" 
      id="perform"/>
    <aop:aspect ref="transaction">
      <!-- 
        前置通知
            1、在目标方法执行之前
            2、前置通知中,方法有一个参数JoinPoint
       -->
      <aop:before method="beginTransaction" pointcut-ref="perform"/>
      <!-- 
        后置通知
           1、在目标方法执行之后
           2、能够获取目标方法的返回值
               returning="val" val就是通知方法中 后置通知中的参数名称
           3、如果目标方法产生异常,则后置通知不再执行
       -->
      <aop:after-returning method="commit" pointcut-ref="perform" returning="val"/>
      <!-- 
        异常通知
                  获取目标方法抛出的异常信息
          throwing="ex"
       -->
      <aop:after-throwing method="throwingMethod" pointcut-ref="perform" throwing="ex"/>
      <!-- 
        最终通知
       -->
      <aop:after method="finallyMethod" pointcut-ref="perform"/>
      <!-- 
        环绕通知
            能够控制目标方法的执行
            环绕通知可以有返回值,这个返回值就是代理对象的方法的返回值
            前置通知和后置通知只能在目标方法执行之前和之后加代码,但是不能控制目标方法的执行
       -->
      <aop:around method="aroundMethod" pointcut-ref="perform"/>
    </aop:aspect>
  </aop:config>
</beans>

核心类切面代码:

package com.itheima11.spring.aop.xml.transaction;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
public class Transaction {
  /**
   * 前置通知 参数:JoinPoint 连接点:客户端调用哪个方法,这个方法就是连接点
   */
  public void beginTransaction(JoinPoint joinPoint) {
    System.out.println("目标类:" + joinPoint.getTarget().getClass());
    System.out.println("目标方法的名称:" + joinPoint.getSignature().getName());
    System.out.println("目标方法的参数:" + joinPoint.getArgs().length);
    System.out.println("begin transaction");
  }
  /**
   * 后置通知 val接收目标类的目标方法的返回值
   */
  public void commit(JoinPoint joinPoint, Object val) {
    System.out.println("返回值:" + val);
    System.out.println("commit");
  }
  /**
   * 异常通知 不管是否目标方法是否抛出异常,都会执行这个方法,相当于finally
   */
  public void throwingMethod(JoinPoint joinPoint, Throwable ex) {
    System.out.println(ex.getMessage());
  }
  /**
   * 最终通知
   */
  public void finallyMethod() {
    System.out.println("finally method");
  }
  /**
   * 环绕通知 可以控制目标方法的是否执行
   */
  public Object aroundMethod(ProceedingJoinPoint joinPoint) throws Throwable {
    System.out.println("around method");
    return joinPoint.proceed();// 执行目标方法,如果不写行代码 则目标方法不会执行
  }
}

客户端代码

package com.itheima11.spring.aop.xml.transaction;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
/**
 * aop的原理
 *     1、启动spring容器
 *     2、spring容器会为personDao和transaction实例化
 *     3、spring容器解析aop:config的配置
 *         当spring容器解析到切入点表达式的时候,就会把切入点表达式解析出来
 *            会让切入点表达式的类和spring容器中的类进行匹配
 *               如果匹配成功,则会为该对象创建代理对象
 *                  代理对象的方法形成=通知+目标方法
 *               如果匹配不成功,则会报错
 *     4、在客户端context.getBean时,如果当前的对象有代理对象,则返回代理对象
 *              如果没有代理对象返回对象的本身
 *     5、在spring内部会检查目标类有没有实现接口
 *           如果目标类实现了接口,则采用jdkproxy产生代理对象
 *           如果目标类没有实现接口,则采用cglibproxy产生代理对象
 * @author zd
 *
 */
public class PersonDaoTest {
  @Test
  public void testSpring(){
    ApplicationContext context = 
        new ClassPathXmlApplicationContext("applicationContext.xml");
    PersonDao personDao = (PersonDao)context.getBean("personDao");
    String s = personDao.savePerson();
    System.out.println(s);
  }
}

结果:


20161231111015380.png

小编在都将重要的注释写在代码中,请读者自行体会。上面这个demo就是对于springAOP中常用的几个通知的实现,在实际的场景我们需要不同的需求来运用不同的通知来实现。


当我们对这个模式比较熟悉以后,里面比较重要是我们切入点表达式的编写,我们不在用原先的if。。else。。来实现,我们根据需求编写表达式实现。所以我们需要熟悉表达式的编写。


在下面的博客中将会利用这些基本知识,实现具体的业务需求。

目录
相关文章
|
Java 开发者 Spring
Spring Framework 中的 @Autowired 注解:概念与使用方法
【4月更文挑战第20天】在Spring Framework中,@Autowired 注解是实现依赖注入(Dependency Injection, DI)的一种非常强大的工具。通过使用 @Autowired,开发者可以减少代码中的引用绑定,提高模块间的解耦能力
1222 6
|
JavaScript 前端开发
JavaScript实现div块跟随鼠标移动效果
JavaScript实现div块跟随鼠标移动效果 前面讲了这么多DOM事件有关的属性等,现在我们进行一些相关的练习,实现div块跟随鼠标移动效果,如图: 在这里插入图片描述 HTML代码: &lt;div id=&quot;box&quot;&gt;&lt;/div&gt; 1 CSS代码: *{ margin: 0; padding: 0; } body{ width: 2000px; height: 2000px; } #box{ width: 200px; heigh
JavaScript实现div块跟随鼠标移动效果
|
10月前
|
弹性计算 负载均衡 网络协议
配置SLB监听器
配置SLB监听器
488 63
|
传感器 人工智能 搜索推荐
人工智能(AI)与物联网(IoT)的融合是当今技术领域的一个重要趋势
人工智能(AI)与物联网(IoT)的融合是当今技术领域的一个重要趋势
|
数据采集 监控 搜索推荐
ERP系统中的财务指标与绩效评估解析
【7月更文挑战第25天】 ERP系统中的财务指标与绩效评估解析
520 0
|
Java C++
jni传递对象
【5月更文挑战第4天】
164 2
|
机器学习/深度学习 分布式计算 算法
MaxCompute 的 MapReduce 与机器学习
【8月更文第31天】随着大数据时代的到来,如何有效地处理和分析海量数据成为了一个重要的课题。MapReduce 是一种编程模型,用于处理和生成大型数据集,其核心思想是将计算任务分解为可以并行处理的小任务。阿里云的 MaxCompute 是一个面向离线数据仓库的计算服务,提供了 MapReduce 接口来处理大规模数据集。本文将探讨如何利用 MaxCompute 的 MapReduce 功能来执行复杂的计算任务,特别是应用于机器学习场景。
269 0
|
存储 自然语言处理 前端开发
深入浅出JVM(七)之执行引擎的解释执行与编译执行
深入浅出JVM(七)之执行引擎的解释执行与编译执行
|
网络协议
有关DNS64的知识点
总之,DNS64在IPv6-only环境中扮演着重要的角色,通过地址转换使得IPv6设备能够访问IPv4资源,促进了IPv6的部署和演进。
919 0
|
人工智能 自然语言处理 搜索推荐
AIGC在商业银行中的应用现状
【1月更文挑战第11天】AIGC在商业银行中的应用现状
444 3
AIGC在商业银行中的应用现状