Spring入门3.AOP编程
Spring入门3.AOP编程
代码下载: 链接: http://pan.baidu.com/s/11mYEO 密码: x7wa
前言:
前面学习的知识是Spring在Java项目中的IoC或DJ,这些是Spring中的基础,我们进一步学习Spring的其他知识,IoC是Spring的核心内容之一,另一个同等重要的内容便是AOP,也就是所谓的面向切面编程的知识,也许现在你不知道这是个什么东西,其实我只是之前听说过,没有具体的了解过,所以一起学习AOP的知识。
本章的主要知识:
AOP基本概念、Advice类的编写、切面的不同类型和配置切面的方法、Spring对于事务管理的支持、事物编程式事物管理以及其配置方式。(感觉是不是很高深啊,我也是第一次接触,不用害怕,我们都掌握了很好的Java编程基础,这些都是基于Java语言的,就不会有太大的困难)
1. Spring AOP
AOP(Aspect Oriented Programming),面相切面编程,他作为面相对象编程的一种补充,是一种比较成熟的编程思想。AOP和OOP相辅相成,面相对象编程将程序分为不同层次的对象,面相切面编程将程序运行的过程分解成为各个切面,可以认为,面相对象编程是从静态角度考虑程序的结构,而面相切面编程则是从动态的角度去考虑程序的运行过程。
利用继承的思想,可以实现代码的复用,但是随着软件规模的增加,应用的升级,软件中就会出现很多重复的代码,而且这些事无法通过继承的方式进行重用和管理的,在系统的升级和管理上带来诸多的不便。AOP是被称为一种“横切”技术,剖开封装对象的内部,并将那些影响了多个类的行为封装到一个重用的模块中,被称之为Aspect,也就是切面。通过切面可以将那些和业务无关的缺位业务模块共同调用的逻辑封装起来,从而减少了系统的重复代码,降低了模块之间的耦合度,有利于系统的可维护性和扩展性。
AOP把软件系统分为两个部分:核心关注点和横切关注点。核心关注点是业务处理的主要流程,而横切关注点是于核心关注点无关的部分,常常发生在核心关注点的周围,并且代码类似,比如日志记录,权限检查等等。
横切关注点虽然于核心关注点的实现无关,但确是一种更为通用的业务,横切关注点离散的穿插在核心业务中,导致系统中的每一个模块都会和这些业务有很高的依赖心。OOP提高了代码的重用,AOP将分散在业务逻辑中的相同代码,通过横向切割的方式抽取成一个独立的模块,使得业务逻辑更加简洁
AOP的核心思想:将程序中的商业逻辑和对其提供的通用服务进行分离。
2.AOP术语
连接点(joinpoint):一个类或者一段程序代码拥有一些具有边界性质的特定点,就是连接点,实际上,就是程序执行到某个特定的位置,比如类初始化前,初始化之后,某个方法调用前,调用后,异常处理等等。通常有很多的连接点,比如方法的调用前,调用后,抛出异常等等,Spring框架仅仅支持函数的连接点。
切入点(PointCut):被增强的连接点,AOP通过切入点定位到特定的连接点,当某个连接点满足指定的条件,该连接点将被添加增强(Advice),那么该连接点就成为一个切入点。
增强(Advice):织入到目标类特定连接点的一段程序代码。由于增强既包含了用于添加到目标连接点上的一段执行逻辑,又包含了用于定位连接点的方位信息,所以在Spring中提供的增强接口都是带方位名的,BeforeAdvice, AfterAdvice.
目标对象(Target):增强被组织的目标类。如果没有AOP,目标业务类需要自己实现所有的逻辑,借助AOP框架技术,业务类可以只实现核心业务逻辑,而日志、事务管理等横切关注点可以使用AOP动态组织到特定的连接点上。
引入(Introduction):一种特殊的Advice,他为类添加了一些属性和方法,这样即使一个业务原本没有实现某个接口,通过AOP的引入功能,也可以动态为该业务添加接口的实现逻辑,让业务类成为这个接口的实现类。
织入(Weaving):将Advice添加到目标类具体连接点的过程。他将目标类、Advice整合在一起,根据不同的实现技术,AOP有三种不同的实现方式:编译期织入,通常要求使用特殊的Java编译期;类装载期织入,要求使用特殊的类状态器;动态代理织入,在运行期为目标添加Advice并且创建一个目标类型的子类以及对象。Spring采用的是动态代理的方式。
代理(Proxy):一个类被AOP织入Advice之后,就会产生一个结果类,该结果类就是融合了目标类和Advice逻辑的代理类,根据不同的代理方式,该结果类既可能是和目标类有着相同接口的类,也可能是目标类的子类,所以可以使用调用目标类的方式调用该结果类。在Spring中,AOP可以是JDK的动态代理,也可以是CGLIB代理。当明确指定目标类实现何种接口的时,Spring使用动态代理,否则使用CGLIB进行字节码增强。
切面(Aspect):切面是由切入点和Advice组成。既包括Advice逻辑的定义,也包括了切入点的定义,SpringAOP是负责实施切面的框架,将切面所定义的Advice组织到切面指定的连接点中。
AOP编程中,开发人员需要了解的有三个方面:
定义普通的业务类、
定义切入点(一个切入点可以很且多个业务逻辑)、
定义Advice(Advice就是在AOP框架为普通业务组件织入的处理逻辑)
对于AOP,最关键的就是定义切入点(PointCut)和Advice,定义了合适的PointCut和Advice,Spring会自动生成AOP代理。
3.Advice类型
根据目标类连接点位置的不同,Spring支持五中类型的Advice:
前置Advice:在某个连接点方法执行之前,如果没有异常,则该连接点一定会被执行,在Spring框架中,BeforeAdvice接口表示前置Advice,Spring只支持方法级别的Advice,所以也可以使用MethodBeforeAdvice接口来表示前置Advice,用于在目标方法执行之前实施
后置Advice:指的是连接点方法无论在任何情况下推出时所执行的Advice,也就是无力啊是连接点方法是正常退出,还是抛出异常,都会执行Advice。Spring AOP使用AfterAdvice。
返回后Advice:连接点方法正常执行退出,Spring中使用的AfterReturnAdvice
抛出异常Advice:抛出异常后执行的Advice,Spring中使用的是ThrowsAdvice
环绕Advice:指的是包围连接点的方法的Advice,这一种Advice比较强大,可以代替前面所有的advice. Spring中使用的是MethodInterceptor接口表示。在目标方法执行前后实施的Advice。
SpringAOP配置方式:
基于XML配置文件的管理方式:使用Spring配置文件来定义切入点和Advice
基于Annotation的零配置方式:使用@Aspect @Pointcut的方式定义切入点和Advice
配置Advice的时候主要依赖一下几个元素:
<aop:before../> <aop:after ../> <aop:after-returning/> <aop:after-throwing><aop:around>
这些元素都不支持子元素,所以使用的是属性的方式,一些属性如下:
pointcut: 指定一个切入点表达式,Spring将在匹配表达式的连接点时织入该Advice
pointcut-ref: 指定一个已经存在的切入点的名称。
method:该属性指定一个方法名称,它对应切面中的定义的Advice逻辑方法
throwing:该属性只针对<after-throwing>有效,用于指定一个形参的名字,通过形参可以访问目标方法抛出的异常传递
returning:仅针对<after-reurning 有效,用于指定一个形参名字,AfterReturning的处理方法,可以使用形参访问目标方法的返回值。
4.基于XMl配置文件的Spring AOP
在Spring的配置文件中,所有切面(Aspect)、切入点(Pointcut)和Advice都必须在<aop:config/>元素内部定义。在<beans></<beans>中可以包含多个<aop:config>元素,一个<aop:config> 可以包含多个<pointcut> <advisor><aspect>,并且这三个元素必须是按照这个顺序来定义。
配置切面
通过<aop:aspect../>元素进行声明的,该元素必须放在<aop:config../>中。使用<aop:aspect../>来配置切面的时候,实际上是将一个已有的Spring Bean转换成为切面Bean,所以首先要定义一个普通的SpringBean。由于切面Bean可以当做一个普通的Spring Bean 来配置,所以可以为该切面Bean配置依赖注入,当切面Bean定义完成之后,通过<aop:aspect../>元素中使用ref属性引用该bean,就可以将一个普通的bean转换成为切面bean。
<aop:aspect>需要指定的属性有
id(切面标志名)、
ref 指定该属性引用的普通bean作为切面bean、
order(指定该切面bean的优先级,order值越小,该切面对应的优先级越高)
创建一个切面类:
public class AspectBean {
public void checkAuth(){
System.out.println("AspectBean.checkAuth()");
}
public void release(){
System.out.println("AspectBean.release()");
}
public void log(Object result){
if(result ==null){
System.out.println("database no data you want");
}else{
System.out.println("database has data you want");
}
}
public void processException(Throwable ex){
System.out.println("Exception information:" + ex.getMessage());
}
public void processInTrans(ProceedingJoinPoint joinpoint) throws Throwable {
System.out.println("start transtraction...");
joinpoint.proceed();
System.out.println("end transtraction....");
}
}
在该切面类中,一共有五个方法,最后一个是表示满足条件的时候,目标类方法进行相应的事务处理过程。至于以上方法如何被调用,这些和Advice配置有关。
通过配置<aop:aspect../>把上面创建的AspectBean类转换成为切面bean:
<?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"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-3.2.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-3.2.xsd"
default-lazy-init="true">
<bean id="aspectBean" class="com.yang.aspect.AspectBean"/>
<aop:config>
<aop:aspect id="adviceAspect" ref="aspectBean">
<!-- 还没有添加Advice配置信息 -->
</aop:aspect>
</aop:config>
</bean>
上述配置信息利用applicationContext.xml中的<aop:config></aop:config>用<aop:aspect></aop:aspect>声明一个id是adviceAspect的切面bean,然后利用ref属性引用id为aspectBean的Spring普通的bean。但是还暂时没有配置Aspect的信息,所以暂时是没有切面作用的。
更进一步,学习Advice配置信息
创建一个目标接口UserService,然后分别说明之前介绍的五中Advice配置文件中的配置方法:
<?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"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-3.0.xsd"
default-lazy-init="true">
<!—这一句十分重要,如果没有这一句,使用XML配置的AOP,在编译期间,就会因为加载applicationContext配置文件出错,但是如果使用的是注解的方式,虽然不会导致程序崩溃,但是Spring的AOP根本不会骑任何作用,就是不会执行AOP的代码-->
<aop:aspectj-autoproxy/>
<!---->
<bean id="aspectBean" class=" com.yang.aspect.AspectBean"></bean>
<bean id="userService" class="com.yang.service.impl.UserServiceImpl"></bean>
<aop:config proxy-target-class="true">
<aop:aspect id="myadvice" ref="aspectBean">
<aop:before method="checkAuth" pointcut="execution(* com.yang.service.UserService.*(..))"/>
<aop:after-returning method="log" pointcut="execution(* com.yang.service.UserService.select(..))" returning="result"/>
<aop:after-throwing method="processException" pointcut="execution(* com.yang.service.UserService.*(..))" throwing="ex"/>
<aop:around method="proceedInTrans" pointcut="execution(* com.yang.service.UserService.*(..))"/>
<aop:after method="release" pointcut="execution(* com.yang.service.UserService.*(..))"/>
</aop:aspect>
</aop:config>
</beans>
做一下简单的讲解:
在Spring AOP的配置文件中,使用<aop:aspectj-autoproxy/>是十分重要的,不然会报错。同时对于参数传递,在returning 和throwing的参数名称必须是和函数中的参数名称保持一致,否则也会报错。
对于配置切面的时候,pointcut的配置方式中execution(* com..*.*service.*(..))指的是以com开头的以service结尾的包中的所有class中的所有方法,参数可以是任意的,都会调用该Advice这一个配置的方法。
同时对于around,其中方法的执行是在切入点函数执行之前运行前面的代码,执行之后运行后面的代码。
public void processInTrans(ProceedingJoinPoint joinpoint) throws Throwable {
System.out.println("start transtraction...");
joinpoint.proceed();
System.out.println("end transtraction....");
}
}
代理技术:之前介绍的代理技术有两种形式,CGLIB和JDK动态代理机制。在<aop:config>中使用的是属性proxy-target-class表示的,当设置成为true的时候,切面使用的是CGLIB代理的形式;而当设置成为false的时候,使用的是JDK动态代理的机制。对于不通过的<aop:config>可以使用不同的代理技术。
YangTengfei
2013.11.26
Spring入门3.AOP编程的更多相关文章
- Spring入门4.AOP配置深入
Spring入门4.AOP配置深入 代码下载 链接: http://pan.baidu.com/s/11mYEO 密码: x7wa 前言: 之前学习AOP中的一些概念,包括连接点.切入点(pointc ...
- 使用spring框架进行aop编程实现方法调用前日志输出
aop编程 之使用spring框架实现方法调用前日志输出 使用spring框架实现AOP编程首先需要搭建spring框架环境: 使用Spring框架实现AOP工程编程之后,不需要我们去写代理工厂了,工 ...
- Spring Boot学习——AOP编程的简单实现
首先应该明白一点,AOP是一种编程范式,是一种程序设计思想,与具体的计算机编程语言无关,所以不止是Java,像.Net等其他编程语言也有AOP的实现方式.AOP的思想理念就是将通用逻辑从业务逻辑中分离 ...
- Spring框架的AOP编程,最通俗的语言解释,易懂易学
第七章:AOP技术 前言: AOP技术是根据动态代理设计模式进行的技术.动态代理技术分jdk动态代理和cglib动态代理 jdk动态代理特点: (1)继承java.lang.reflect.proxy ...
- Spring入门篇——AOP基本概念
1.什么是AOP及实现方式 什么是AOP AOP:Aspect Oriented Programming的缩写,意为:面向切面编程,通过预编译方式和运行期动态代理实现程序功能的统一维护的一种技术 主要 ...
- Spring入门介绍-AOP(三)
AOP的概念 AOP是面向切面编程的缩写,它是一种编程的新思想.对我们经常提起的oop(面对对象编程)有一定的联系. AOP和OOP的关系 AOP可以说是oop的某一方便的补充,oop侧重于对静态的属 ...
- Spring入门之AOP篇
听了几节IT黑马营的SPRING课程,照着例程写了一个SPRING 中AOP的例子: 一.准备工作 下载复制或配置JAR包.图方便,我将下载的SPRING包都加上去了.另外还需要aspectj的两个 ...
- Spring入门之AOP实践:@Aspect + @Pointcut + @Before / @Around / @After
零.准备知识 1)AOP相关概念:Aspect.Advice.Join point.Pointcut.Weaving.Target等. ref: https://www.cnblogs.com/zha ...
- JavaEE开发之Spring中的依赖注入与AOP编程
上篇博客我们系统的聊了<JavaEE开发之基于Eclipse的环境搭建以及Maven Web App的创建>,并在之前的博客中我们聊了依赖注入的相关东西,并且使用Objective-C的R ...
随机推荐
- pc端弹框
pc弹框插件:http://aui.github.io/artDialog/doc/index.html#quickref-bubble PC端,手机端,layui很好用,分页啥的:http://ww ...
- iOS 绘制一个表盘时钟,秒针效果可以“扫秒/游走”
最近自己 也尝试写了一个表盘时钟,初衷源于等车时候一个老奶奶问时间,我打开手机,时间数字对我来说相对敏感,但是老奶奶是看不清的,我想识别 还是看表盘 老远 看时针分针角度就可以识别当前时间. 于是我想 ...
- 前端学习笔记之ES6快速入门
0x1 let和const let ES6新增了let命令,用于声明变量.其用法类似var,但是声明的变量只在let命令所在的代码块内有效. { let x = 10; var y = 20; } x ...
- Tomcat的工作模式和运行模式
(1)工作模式 Tomcat作为servlet容器,有三种工作模式: 1.独立的servlet容器,servlet容器是web服务器的一部分: 2.进程内的servlet容器,servlet容器是作为 ...
- java.lang.NoSuchMethodError: net.sf.cglib.core.Signature
今天二次开发Dubbo-admin的管理平台,开启tomcat直接报错,错误关键字为“ java.lang.NoSuchMethodError: net.sf.cglib.core.Signature ...
- web.xml servlet、servlet-mapping配置
Servlet常称为服务器端小程序,即运行在服务器端的程序,用于处理及响应客户的请求. Servlet类是个特殊的java类,继承于HttpServlet. --------------------- ...
- 20145329 《Java程序设计》实验五总结
实验内容: 1.用老师代码编写,实现服务器与客户端. 2.客户端与服务器连接 3.客户端中输入明文,利用DES算法加密,DES的秘钥用RSA公钥密码中服务器的公钥加密,计算明文的Hash函数值,一起传 ...
- 【前端】Vue.js实现简单价格计算器
价格计算器 实现效果: 实现代码及注释: <!DOCTYPE html> <html> <head> <title>价格计算器</title> ...
- struts2的refreshModelBeforeResult
首先想介绍的是struts2的原型驱动ModelDriven机制. 所谓的ModelDriven,就是把一个实体类当成页面数据的收集对象.用法看起来像下面这个样子 <span style=&qu ...
- CentOS7系统安装配置samba服务
# 查询是否已经安装了Samba rpm -qi samba # 安装 yum -y install samba samba-client samba-common # 添加新用户 useradd s ...