Spring AOP的五大通知及作用详解

这是我在博客中找到的一篇解释得非常全面的文章。
在这篇博客中我们就用配置文件的方式来来介绍AOP中的五大通知(也可以用注解)。

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

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

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

最终通知(finally);不管目标方法是否有异常都会执行,相当于try。。catch。。finally中的finally

环绕通知(round):可以控制目标方法是否执行

下面就通过一个栗子来总结一下这几个通知应该如何使用.

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

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

首先来看一下配置文件:

<?xml version="1.0" encoding="UTF-8"?>




<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>

核心类切面代码:

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);
}
}
结果:


作者:郑浩-
来源:CSDN
原文:https://blog.csdn.net/hao134838/article/details/53457619
版权声明:本文为博主原创文章,转载请附上博文链接!

发布了42 篇原创文章 · 获赞 1 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/qq_41935885/article/details/88806698