Spring学习笔记三(AOP中的那些事)

1.前言

前两篇博客介绍了一下,Spring中的IOC容器,这篇来讲解一下Spring中的AOP的知识。

 2.AOP基础知识

2.1 概念

AOP是一种面向切面编程,一种软件工程的编程范式。AOP关注的是程序中的共性的功能,开发时,将共性功能抽取出来制作成独立的模块,此时原始代码中将不再具有这些被抽取出来的共性功能代码。因此加强了代码的复用性,同时程序开发时可以只考虑个性化功能,不需要考虑共性的功能。

2.2 基本知识点

连接点:具有特定功能的方法,一般方法

切入点:具有共性功能的方法的统称的一种称呼方式。

目标对象:包含切入点的类

通知:将共性功能抽取走,制作成独立的功能模块。

切面:切入点与通知匹配的一种情况。

AOP代理:运行过程中使用AOP创建代理对象进行运行,运行过程中将抽取的功能执行,该过程由AOP自动完成,所以称为AOP代理。

织入:将抽取的功能加入原始功能运行的整个过程叫做织入,织入控制的是字节码

工作流程

开发时,制作功能类(目标对象),将其中的方法中的通用功能(通知)抽取出来,制作成独立的类(通知类),原始目标对象中的方法(切入点)不再进行通用功能的制作。该功能被抽取后,无法完成完整的业务逻辑,需要在运行时将通知加入到对应的位置执行。为了完成此操作,必须将切入点与通知类进行一对一的对应关系设定(切面)

运行过程

运行时,Spring一直监控切面中所配置的切入点对应的方法的执行,发现执行了该方法,使用AOP的代理机制,创建代理对象(AOP代理),将原始方法(切入点)与通知进行融合,形成一个完成的业务逻辑进行运行,此过程称为织入。

3.AOP实践

3.1 简单的Demo

制作目标对象

<span style="font-family:SimSun;font-size:18px;"><span style="font-family:SimSun;font-size:18px;">//目标对象类
public class UserService {
	//连接点//切入点
	public void add(){
		//共性功能被抽取走了,放入到了MyAdvice类中的fn方法里
		System.out.println("add");
	}
	//连接点
	public void delete(){
		System.out.println("bbbbbb");
		System.out.println("delete");
	}
}
</span></span>

制作通知

<span style="font-family:SimSun;font-size:18px;"><span style="font-family:SimSun;font-size:18px;">//通知类
public class MyAdvice {
	//具有共性功能的方法:通知
	public void fn(){
		//共性功能
		System.out.println("aaaaa");
	}
}
</span></span>

AOPXML配置

<span style="font-family:SimSun;font-size:18px;"><span style="font-family:SimSun;font-size:18px;"><?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.xsd
	http://www.springframework.org/schema/aop
	http://www.springframework.org/schema/aop/spring-aop.xsd
	">

	<!-- 配置通知类为Bean -->
	<bean id="myAdvice" class="com.aop.MyAdvice">
	</bean>

	<bean id="UserService" class="com.aop.UserService">
	</bean>

	<!-- 配置AOP -->
	<aop:config>
		<!-- 配置切面 ref对应的通知类的beanID -->
		<aop:aspect ref="myAdvice">
			<!-- 配置通知类与关系(切入点与通知方法) -->
			<!-- <aop:before method="fn"
				pointcut="execution(public void com.aop.UserService.add())" /> -->

				<!-- 不限定修饰符 -->
				<!-- <aop:before method="fn"
				pointcut="execution( void com.aop.UserService.add())" /> -->
				<!-- 不限定返回值 -->
				<!-- <aop:before method="fn"
				pointcut="execution( * com.aop.UserService.add())" /> -->

				<!--  <aop:before method="fn"
				pointcut="execution( * *.aop.UserService.add())" />  -->

			<!-- 	 <aop:before method="fn"
				pointcut="execution( * com.*.UserService.add())" />  -->

				<!--  <aop:before method="fn"
				pointcut="execution( * *..*.UserService.add())" />  -->

	<!-- 			 <aop:before method="fn"
				pointcut="execution( * *..UserService.add())" />  -->

				<!-- <aop:before method="fn"
				pointcut="execution( * *..*Service.add())" />  -->

				<!-- <aop:before method="fn"
				pointcut="execution( * *..User*.add())" />  -->

				<!-- <aop:before method="fn"
				pointcut="execution( * *..*.*())" />  -->

				<!-- 匹配一个参数 -->
			<!-- 	<aop:before method="fn"
				pointcut="execution( * *..*.*(*))" />  -->

				<!-- 匹配两个任意参数 -->
				<!-- <aop:before method="fn"
				pointcut="execution( * *..*.*(*,*))" />  -->

				<!-- 匹配任意参数 -->
			<!-- 	<aop:before method="fn"
				pointcut="execution( * *..*.*(..))" />  -->

				<!-- 匹配至少一个参数 -->
				<!-- <aop:before method="fn"
				pointcut="execution( * *..*.*(*,..))" />  -->

				<!-- 匹配第一个参数是int,后面无所谓 -->
					<!-- <aop:before method="fn"
				pointcut="execution( * *..*.*(int,..))" />  -->

				<aop:around method="fn" pointcut="execution( * *..*.*(..))"/>
		</aop:aspect>
	</aop:config>

</beans>
</span></span>

注意:pointcut配置的是切入点表达式,pointcut-ref配置的是切入点引用对象,method配置的切入点执行的通知方法。

3.2 通知类别

before:前置通知(应用:各种校验)

在方法执行前执行,如果其中抛出异常

after:后通知(应用:清理现场)

方法执行完毕后执行,无论方法中是否出现异常

afterReturning:返回后通知(应用:常规数据处理)

方法正常返回后执行,如果方法中抛出异常,无法执行

afterThrowing:抛出异常后通知(应用:包装异常信息)

方法抛出异常后执行,如果方法没有抛出异常,无法执行

around:环绕通知(应用:十分强大,可以做任何事情)

方法执行前后分别执行,可以阻止方法的执行

//环绕通知
	public void around(ProceedingJoinPoint pjp) throws Throwable{
		System.out.println("around before......");
		//调用原始方法
		pjp.proceed();
		System.out.println("around after......");
	}

1.通知的配置格式

	<aop:before pointcut-ref="pt2" method="before"/>
			<aop:after pointcut-ref="pt2" method="after"/>
			<aop:after-returning pointcut-ref="pt2" method="afterReturning"/>
			<aop:after-throwing pointcut-ref="pt2" method="afterThrowing"/>
			<aop:around pointcut-ref="pt2" method="around"/>

  2.通知顺序:与配置顺序有关

多个切面间

先声明的before先运行,

后声明的before后运行

先声明的after后运行

后声明的after先运行

总结:配置时以最终运行顺序为准

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-10-24 11:10:37

Spring学习笔记三(AOP中的那些事)的相关文章

OpenCv学习笔记(三)---OpenCv中基本数据类型--Point,Size,Rect,Scalar,Vec3b类类型的详细解释及其OpenCv中源代码的详细分析

/********************************************************************************************* 程序功能: OpenCv的基本数据结构源代码的解读,我们常用的OpenCv的基本数据结构有六种: 1--Point类 2--Size类 3--Rect类 4--Scalar类 5--Vec3b--向量模板类 6--Range类 编写环境: OpenCv2.4.8+VS2010 地点时间: 陕西师范大学 201

Spring in Action 学习笔记三-AOP

面向切面的Spring 2015年10月9日 11:30 ? ? ? ? ? ? 屏幕剪辑的捕获时间: 2015-10-9 14:30 ? ? ? ? ? ? 屏幕剪辑的捕获时间: 2015-10-9 14:38 ? ? ? ? ? ? 屏幕剪辑的捕获时间: 2015-10-9 14:38 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 屏幕剪辑的捕获时间: 2015-10-10 14:42 ? ? ? ? ? ? ? ? ? 屏幕剪辑的捕获时间: 2015-10-10 14:43

Spring学习笔记(三)之装配Bean

除了组件扫描与自动装配之外还有基于Java代码的装配与基于XML的装配. 有一些场景是我们不能用自动装配的,比如我们要给第三方库中的组件装配到我们的应用中,这时自动装配无效,因为自动装配只能扫描本应用中的包. 这时我们就要在基于代码代码的装配和基于XML的装配中进行选择,前面我们说到了JavaConfig相比XML更强大更安全. 一.基于Java代码的装配Bean(JavaConfig) 但是JavaConfig又与Java有所区别. 概念上  JavaConfig是配置 与应用的其他代码业务逻

Spring学习笔记--在SpEL中筛选集合

要用到Spring的util(包括util:list等),xml文件中的beans中需要添加一些有关util的信息: <?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance&q

jQuery学习笔记(三)jQuery中的动画

1 show() 方法和hide() 方法  (显示和隐藏) show() 方法和hide() 方法是jQuery中基本的动画方法.在HTML文档里,为一个元素调用hide() 方法,会将该元素的display样式改为“none”. $("element").hide(); //通过hide()方法将element元素隐藏 $("element").css("display","none"); //通过css()方法将elem

spring学习笔记(19)mysql读写分离后端AOP控制实例

在这里,我们接上一篇文章,利用JNDI访问应用服务器配置的两个数据源来模拟同时操作不同的数据库如同时操作mysql和oracle等.实际上,上个例子可能用来模拟mysql数据库主从配置读写分离更贴切些.既然如此,在本例中,我们就完成读写分离的模拟在web端的配置实例. 续上次的例子,关于JNDI数据源的配置和spring datasource的配置这里不再重复.下面着重加入AOP实现DAO层动态分库调用.可先看上篇文章<spring学习笔记(18)使用JNDI模拟访问应用服务器多数据源实例 >

Spring学习笔记(三)

Spring学习笔记(三) AOP 一.使用Annotation方式实现AOP.步骤: xml里加入配置:<aop:aspectj-autoproxy /> <?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org

Spring Batch学习笔记三:JobRepository

此系列博客皆为学习Spring Batch时的一些笔记: Spring Batch Job在运行时有很多元数据,这些元数据一般会被保存在内存或者数据库中,由于Spring Batch在默认配置是使用HSQLDB,也就是说在Job的运行过程中,所有的元数据都被储存在内存中,在Job结束后会随着进程的结束自动消失:在这里我们推荐配置JobRepository去使用MySQL. 在这种情况下,Spring Batch在单次执行或者从一个执行到另外一个执行的时候会使用数据库去维护状态,Job执行的信息包

不错的Spring学习笔记(转)

Spring学习笔记(1)----简单的实例 ---------------------------------   首先需要准备Spring包,可从官方网站上下载.   下载解压后,必须的两个包是spring.jar和commons-logging.jar.此外为了便于测试加入了JUnit包.   在Myeclipse中创建Java项目.   编写一个接口类,为了简单,只加入了一个方法.   Java代码   1.package com.szy.spring.interfacebean;