Spring与AOP

AOP简介

AOP,Aspect Orient Programming,面向切面编程。是一种概念,是一种思想,其实现者很多,Spring就是实现者之一。

AOP是OOP(面向对象编程)的一种补充。OOP是从静态角度考虑程序的结构,而AOP是动态角度考虑程序的运行过程。

Spring用于降低耦合度。IoC用于降低主业务逻辑之间的耦合度;AOP用于降低主业务逻辑与系统级服务(交叉业务逻辑)间的耦合度,将系统级服务在运行时织入到主业务逻辑之中。

Spring的AOP的底层工作原理,是使用动态代理对主业务进行增强。而动态代理使用的是JDK的Proxy与CGLIB两种动态代理。

AOP的知识点:

  • 切面:切面指的就是交叉业务逻辑比如记录日志事务管理等等。就是要对主业务逻辑进行增强的部分。AOP编程常见的切面有两种,一种是通知,一种是顾问
  • 织入:就是将切面切入到主业务逻辑的过程,称为织入。
  • 连接点:可以织入切面的目标方法,称为连接点。
  • 切入点:实际织入切面的目标方法。
  • 目标对象:用于被增强的对象。主业务逻辑所在类的对象
  • 通知:是一种切面,可以完成简单的织入功能。例如:可以指定切入的时间点。是方法执行前还是方法结束前或者执行过程中等等时间点。通知会将目标类中所有的方法作为切入点进行织入。
  • 顾问:也是一种切面,其中包含了通知,可以完成更为复杂的织入功能。可以指定具体切入的类和具体方法
  • 引入:一种切面,在不修改源码的前提下,给目标对象增加新的功能。

AOP编程的环境搭建

  • 导入spring-aop的jar包
  • 导入aop联盟的jar包

通知的具体分类:

  • 前置通知MethodBeforeAdvice:用于在主业务方法执行前进行的操作,实现MethodBeforeAdvice接口并实现接口中的方法
public class MyBeforeAdvice implements MethodBeforeAdvice {

	@Override
	public void before(Method method, Object[] args, Object target) throws Throwable {
		System.out.println("执行前置通知-----------------");
	}
}

  • 后置通知AfterReturningAdvice:实现AfterReturningAdvice接口中的通知方法
public class MyAfterAdvice implements AfterReturningAdvice {
    //后置通知可以获取到目标方法的返回值returnValue但是不能修改返回值

	@Override
	public void afterReturning(Object returnValue, Method method, Object[] args, Object target) throws Throwable {
		System.out.println("执行后置通知------------------");
	}
    
}
  • 环绕通知:实现MethodInterceptor接口该接口是AOP联盟提供的,该方法可以调用执行目标方法,可以在目标方法执行前后进行功能增强,也可以修改,目标方法的返回值
public class MyInterceptorAdvice implements MethodInterceptor {

	@Override
	public Object invoke(MethodInvocation invocation) throws Throwable {
		System.out.println("方法执行前代码");
		String result = (String) invocation.proceed();
		System.out.println("方法执行后代码");
		return result.toUpperCase();
	}

}
  • 异常通知:自定义通知类实现ThrowsAdvice接口,该接口中没有具体需要实现的方法,通过查看源码可知,有四个方法可以选择性的实现我们一般实现afterThrowing(Exception ex)方法,该方法可以重载,用来匹配不同类型的异常,异常通知会在目标方法发生异常时执行。

通知的织入

  • 在spring容器中(配置文件)注册通知
  • 注册目标对象
  • 使用动态代理工厂Bean生成增强后的代理对象
	<!-- 注册前置通知 -->
	<bean id="beforeAdvice" class="com.lscw.advices.MyBeforeAdvice"/>
	
	<!-- 注册目标方法 -->
	<bean id="myCar" class="com.lscw.car.carImpl" />
	
	<!-- 使用代理工厂生成代理对象 -->
	<bean id="carProxy"  class="org.springframework.aop.framework.ProxyFactoryBean" >
		<!-- 指定目标类 -->
		<property name="targetName" value="myCar" />
		<!-- 指定织入的通知,可以指定多个,我这只指定一个前置通知 -->
		<property name="interceptorNames" value="beforeAdvice" />
	</bean>
  • 从spring容器中获取代理对象调用执行其中的方法得出结果

顾问Advisor:

  • 切入点顾问:用于指定切入点织入的位置,就是说,你要将切面织入到哪个目标方法。
  • 引入顾问:在不修改目标类的前提下,给目标对象增加新的功能。

切入点顾问:

  • 名称匹配方法切入点顾问
  • 正则表达式方法切入点顾问:正则表达式方法切入点顾问中的属性pattern所匹配的是方法的全限定性名称

使用动态代理工厂Bean的缺点:

  1. 从spring中获取的是代理对象而不是目标对象
  2. 每一个目标类都要注册代理对象

默认顾问自动生成器:

Bean名称自动代理生成器:

通过注入属性beanNames和interceptorNames可以指定多个Bean和多个顾问或通知


AspectJ对AOP的实现

AspectJ概述:

  • 什么是AspectJ:AspectJ是一个面向切面的框架,它扩展了Java语言。
    AspectJ定义了AOP语法,所以它有一个专门的编译器用来生成遵守Java字节编码规范的Class文件。
  • AspectJ Spring AOP 之间的关系:

    AspectJ是另外一个框架,与Spring没有任何关系。但,AspectJ与Spring都是AOP的实现者。
    下面要讲述的是:基于Spring环境下的AspectJ对AOP的实现。

AspectJ知识点:

  • AspectJ的通知:前置通知  后置通知  环绕通知  异常通知  最终通知
  • 最终通知:无论是否发生异常都会执行的通知
  • 切入点表达式:使用规范execution(方法返回值 空格 方法的全限定名称 参数列表)

    execution( * com.abc.service.*.*(..)):表示com.abc.service包下的所有方法都是切入点。

    execution( * com.abc.service.*.open*(..)):表示com.abc.service包下的所有以open开头的方法都是切入点。

    execution( * *.service.*.*(..)):表示service包(该service包前只能有一级父包)下的所有方法都是切入点。  

    com.service.ISomeService.doFirst()是匹配的。

    com.abc.service.ISomeService.doFirst()是不匹配的。

    execution( * *..service.*.*(..)):表示service包(该service包前可以有任意级的父包)下的所有方法都是切入点。

    com.service.ISomeService.doFirst()是匹配的。

    com.abc.service.ISomeService.doFirst()也是匹配的

AspectJ的环境搭建:

  • AspectJ的核心jar包
  • spring与AspectJ整合的jar包
  • spring-aop的jar包
  • aop联盟的jar包
  • spring容器中引入对aop的约束
  • 注册aop:aspectJ自动代理生成器

基于注解的AspectJ编程:

  • 注解的介绍:
    @Aspect:该注解作用于类上表示该类为切面类

    @Before:表示前置通知,使用方式:@Before(“execution(“* *..aop15.类名或接口名.方法名(..)”)”)

    @AfterReturning:表示后置通知

    @Arround:环绕通知,定义在该注解下的方法需要添加ProceedingJoinPoint参数

    @AfterThrowing:异常通知,定义了异常注解的方法,应添加Exception参数

    @After:最终通知

    @PointCut:使用了该注解的方法,其方法名可以作为切入点
  • 代码示例:
@Aspect // 表示当前类为切面
public class MyAspect {

	// 前置通知
	@Before("execution(* *..aop15.ISomeService.doFirst(..))")
	public void myBefore() {
		System.out.println("执行前置通知方法");
	}

	// 前置通知
	@Before("execution(* *..aop15.ISomeService.doFirst(..))")
	public void myBefore(JoinPoint jp) {
		System.out.println("执行前置通知方法 jp = " + jp);
	}

	// 后置通知
	@AfterReturning("execution(* *..aop15.ISomeService.doSecond(..))")
	public void myAfterReturning() {
		System.out.println("执行后置通知方法");
	}

	// 后置通知
	// 后置通知可以获取到目标方法的执行结果,但不能改变其值
	@AfterReturning(value = "execution(* *..aop15.ISomeService.doSecond(..))", returning = "result")
	public void myAfterReturning(Object result) {
		System.out.println("执行后置通知方法 result = " + result);
	}

	// 环绕通知
	// 环绕通知不仅可以读取到目标方法的执行结果,还可以改变其值
	@Around("execution(* *..aop15.ISomeService.doSecond(..))")
	public Object myAround(ProceedingJoinPoint pjp) throws Throwable {
		System.out.println("执行环绕通知 -- 目标方法执行之前");
		// 执行目标方法
		Object proceed = pjp.proceed();
		System.out.println("执行环绕通知 -- 目标方法执行之后");
		if (proceed != null) {
			proceed = ((String) proceed).toUpperCase();
		}
		return proceed;
	}

	// 异常通知
	@AfterThrowing("execution(* *..aop15.ISomeService.doThird(..))")
	public void myAfterThrowing() {
		System.out.println("执行异常通知方法");
	}
	
	// 异常通知
	@AfterThrowing(value = "doThirdPointcut()", throwing="ex")
	public void myAfterThrowing(Exception ex) {
		System.out.println("执行异常通知方法 ex = " + ex.getMessage());
	}
	
	// 最终通知
	@After("execution(* *..aop15.ISomeService.doThird(..))")
	public void myAfter() {
		System.out.println("执行最终通知方法");
	}
	// 最终通知
	@After("doThirdPointcut()")
	public void myAfter2() {
		System.out.println("执行最终通知方法2");
	}
	
	// 定义切入点
	@Pointcut("execution(* *..aop15.ISomeService.doFirst(..))")
	private void doFirstPointcut(){}
	@Pointcut("execution(* *..aop15.ISomeService.doSecond(..))")
	private void doSecondPointcut(){}
	@Pointcut("execution(* *..aop15.ISomeService.doThird(..))")
	private void doThirdPointcut(){}
}

基于XML的AspectJ编程:

  • 前置通知:
  • 后置通知:
  • 环绕通知:
  • 异常通知:如果带参数需要注册参数类型和参数名

  • 最终通知:

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。
1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值