码迷,mamicode.com
首页 > 编程语言 > 详细

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

时间:2015-08-11 10:10:08      阅读:182      评论:0      收藏:0      [点我收藏+]

标签:

 

 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先运行

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





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

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

标签:

原文地址:http://blog.csdn.net/luckyzhoustar/article/details/47414255

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!