Spring AOP(面向切面编程)
AOP(Aspect Oriented Programming),也就是面向切面编程,作为面向对象编程的一种补充,AOP已经成为一种比较成熟的编程方式。可以这样理解:OOP是从静态角度考虑程序结构,而AOP是从动态角度考虑程序运行过程。
>为什么要用?
公共业务?复制粘贴?NO
抽象出方法?依赖耦合!NO
AOP专门用于处理系统中分布于各个模块中的交叉关注点的问题,在Java EE应用中,常常通过AOP来处理一些具有横切性质的系统级服务,如事务管理、安全检查、缓存、对象池管理等,AOP已经成为一种非常常用的解决方案。
>AOP实现可分为两类:
- 静态AOP实现:AOP框架在编译阶段对程序进行修改,即:实现对目标类的增强,生成静态的AOP代理类,即生成的*.class已经被改掉了,需要特定的编译器。以AspectJ为代表(针对字节码class文件进行修改)。
- 动态AOP实现:AOP框架在运行阶段生成AOP代理,即:在内存中以JDK动态代理或cglib动态地生成AOP代理类,以实现对目标对象的增强。以Spring AOP为代表。
一般来说,静态AOP实现具有较好的性能,但需要使用特殊的编译器。动态AOP实现是纯Java实现,因此无须特殊的编译器,但是通常性能较差。
>AOP基本概念
AOP从程序运行角度考虑程序的流程,提取业务处理过程的切面。AOP面向的是程序运行中各个步骤,希望以更好的方式来组合业务处理的各个步骤。
AOP框架并不与特定的代码耦合,AOP框架能处理程序执行中特定的切入点pointcut,而不与某个具体类耦合。AOP框架具有如下两个特征。
- 各步骤之间的良好隔离性。
- 源代码无关性。
下面是关于面向切面编程的一些术语。
- 切面(Aspect):切面用于组织多个Advice(增强处理),Advice放在切面中定义。即:被加入执行的代码块。
- 连接点(Joinpoint):程序执行过程中明确的接入点,比如方法的调用,或者异常的抛出。在Spring AOP中,连接点总是方法的调用。
- 增强处理(Advice):AOP框架在特定的切入点上执行的增强处理。增强处理有“around”、“before”、“after”等类型。所谓的增强处理:就是在原代码不改动的情况下,额外多执行的那些代码。
- 切入点(Pointcut):可以插入增强处理的连接点。简而言之,当某个连接点满足指定要求时,该连接点将被添加增强处理,该连接点也就变成了切入点。例如如下代码:
pointcut xxxPointcut():execution(void H*.say*)
每个方法被调用都只是连接点,但如果方法属于H开头的类,且方法以say开头,则该方法的执行将变成切入点。也可以认为符合条件的连接点即为切入点。如何用表达式来定义切入点是AOP的核心,Spring默认使用AspectJ切入点的语法。
- 引入:将方法或字段添加到被处理的类中。
- 目标对象:被AOP框架进行增强处理的对象,也被称为增强对象。如果AOP框架采用的是动态AOP实现,那么该对象就是一个被代理的对象。
- AOP代理:AOP框架创建的对象,简单地说,代理就是对目标对象的增强。Spring中的AOP代理可以是JDK动态代理,也可以是cglib(Code Generation Library:代码生成库)代理。前者为实现接口的目标对象的代理,后者是不实现接口的目标对象的代理。
- 织入(Weaving):将增强处理添加到目标对象中,并创建一个被增强的对象的过程就是织入。织入有两种方式——编译时增强和运行时增强。
由前面的介绍知道,AOP代理就是由AOP框架动态生成一个对象,该对象可作为目标对象使用。AOP代理包含了目标对象的全部方法,但AOP代理中的方法与目标对象的方法存在差异——AOP方法在特定的切入点加入了增强处理,并回调了目标对象的方法。
AOP代理所包含的方法与目标对象的方法示意图如下所示:
>基于xml的AOP处理
(首先要引入AOP的命名空间)
在Spring配置文件中,所有的切面,切入点和增强处理都必须定义在aop:config元素内部。beans元素下可以包含多个aop:config元素,一个aop:config元素可以包含pointcut、advisor和aspect元素,并且这三个元素必须按照彼此顺序来定义。关于aop:config元素所包含的子元素如下图所示:
在上图中已经非常清楚的绘制出aop:config元素下能包含三个有序的子元素:pointcut、advisor和aspect,其中aspect下可以包含多个子元素,通过使用这些子元素就可以在XML文件中配置切面、切入点和增强处理了。
>hello AOP配置
Spring配置:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"xmlns:p="http://www.springframework.org/schema/p" xmlns:c="http://www.springframework.org/schema/c"xmlns:util="http://www.springframework.org/schema/util"xmlns:tx="http://www.springframework.org/schema/tx"xmlns:aop="http://www.springframework.org/schema/aop" xmlns:context="http://www.springframework.org/schema/context"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans-4.0.xsdhttp://www.springframework.org/schema/utilhttp://www.springframework.org/schema/util/spring-util-4.0.xsdhttp://www.springframework.org/schema/contexthttp://www.springframework.org/schema/context/spring-context-4.0.xsdhttp://www.springframework.org/schema/txhttp://www.springframework.org/schema/tx/spring-tx-4.0.xsdhttp://www.springframework.org/schema/aophttp://www.springframework.org/schema/aop/spring-aop-4.0.xsd" default-autowire="byName" ><!-- 自动扫描,配合注解来确定加载哪些类 --> <context:component-scan base-package="com.langsin.dao.implcom.langsin.service.impl"></context:component-scan> <!-- AOP配置 --><!-- 配置一个切面bean --><bean id="repairAspect" class="com.langsin.aop.RepairAspect"/><aop:config><!-- 切点 --><aop:pointcut expression="execution(* com.langsin.dao.impl.RoleDaoImpl.queryRoleList(..))" id="pointcut"/><!-- 切面、切点结合 --><aop:aspect id="aspect" ref="repairAspect"><aop:before method="beforeAspect" pointcut-ref="pointcut"/><aop:after method="afterAspect" pointcut-ref="pointcut"/><aop:around method="aroundAspect" pointcut-ref="pointcut"/></aop:aspect></aop:config>
</beans>
切面类:
package com.langsin.aop;import org.aspectj.lang.ProceedingJoinPoint;/*** RepairAspect 切面类:增强处理类**/
public class RepairAspect {// 进行before增强处理的方法public void beforeAspect() {System.out.println("----目标方法执行之前,Before进行增强处理----");}// 进行after增强处理的方法public void afterAspect() {System.out.println("----目标方法执行之前,After进行增强处理----");}// 进行around增强处理的方法:除了before 和after ,环绕增强处理可以指定目标方法在哪个位置执行,hai可以让目标方法不执行public Object aroundAspect(ProceedingJoinPoint point){System.out.println("----环绕前,around进行增强处理----");try {return point.proceed(point.getArgs());} catch (Throwable e) {// TODO Auto-generated catch blocke.printStackTrace();}System.out.println("----环绕后,around进行增强处理----");return null;}
}
测试类:
@Testpublic void testRoleDao() throws Exception{//容器启动加载String configLocations="SpringConfig.xml";@SuppressWarnings("resource")ApplicationContext context = new ClassPathXmlApplicationContext(configLocations);//获取 形参(要获取bean的id ,获取bean的类型)RoleDao dao = (RoleDao) context.getBean("dao", RoleDao.class);String string = dao.queryRoleList(12);System.out.println(string);}
>基于注解的AOP处理(基于注解的“零配置”方式)
AspectJ允许使用注解定义切面、切入点和增强处理,而Spring框架则可以识别这些注解并根据注解来生成AOP代理。Spring只是使用了和AspectJ 1.5一样的注解,但并没有使用AspectJ的编译器或者织入器,底层依然使用的是Spring AOP,依然是在运行时动态生成AOP代理,并不依赖AspectJ的编译器或者织入器。
为了启用Spring对@AspectJ切面配置的支持,并保证Spring容器中的目标Bean被一个或多个切面自动增强,必须在Spring配置文件中配置如下片段:
<?xml version="1.0" encoding="GBK"?>
<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-4.0.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-4.0.xsd">
<!-- 启动@AspectJ支持 -->
<aop:aspectj-autoproxy/>
</beans>
如果希望完全启动Spring的“零配置”功能,则需要按照Spring的“零配置”方式进行配置。
如果不喜欢用Spring的XML Schema的配置方式,即<aop:aspectj-autoproxy/>这种方式,则应该在Spring配置文件中增加以下片段来启用@AspectJ支持。
<bean class=”org.springframework.aop.aspectj.annotation.AnnotationAwareAspectJAutoPoxyCreater”/>
AnnotationAwareAspectJAutoPoxyCreater类是一个Bean后处理器,该Bean后处理器将会为容器中所有的Bean生成AOP代理。
为了在Spring应用中启动@AspectJ支持,还需要在应用的类加载路径下增加两个AspectJ库:asectjweaver.jar和aspectjrt.jar,直接使用AspectJ安装路径下lib目录中增加的两个JAR文件即可。除此之外,Spring AOP还需要依赖一个aopalliance.jar。
>hello 注解aop
Spring配置:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"xmlns:p="http://www.springframework.org/schema/p" xmlns:c="http://www.springframework.org/schema/c"xmlns:util="http://www.springframework.org/schema/util"xmlns:tx="http://www.springframework.org/schema/tx"xmlns:aop="http://www.springframework.org/schema/aop" xmlns:context="http://www.springframework.org/schema/context"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans-4.0.xsdhttp://www.springframework.org/schema/utilhttp://www.springframework.org/schema/util/spring-util-4.0.xsdhttp://www.springframework.org/schema/contexthttp://www.springframework.org/schema/context/spring-context-4.0.xsdhttp://www.springframework.org/schema/txhttp://www.springframework.org/schema/tx/spring-tx-4.0.xsdhttp://www.springframework.org/schema/aophttp://www.springframework.org/schema/aop/spring-aop-4.0.xsd" default-autowire="byName" ><!-- 这样写以后,指定注解识别,就无法进行依赖注入--> <context:component-scan base-package="com.langsin.dao.implcom.langsin.service.implcom.langsin.aop"><context:include-filter type="annotation" expression="org.aspectj.lang.annotation.Aspect"/></context:component-scan> <!-- AOP配置 :注解--><!-- 启动对AspectJ的零配置的支持 --><aop:aspectj-autoproxy/> </beans>
切面类:
/*** RepairAspect 切面类:增强处理类**/
@Aspect
public class RepairAspect {//配置切入点@Pointcut("execution(* com.langsin.dao.impl.*.*(..))")public void myPointCut(){}// 进行before增强处理的方法@Before("myPointCut()")public void beforeAspect() {System.out.println("----目标方法执行之前,Before进行增强处理----");}// 进行after增强处理的方法@After("myPointCut()")public void afterAspect() {System.out.println("----目标方法执行之前,After进行增强处理----");}// 进行around增强处理的方法:除了before 和after ,环绕增强处理可以指定目标方法在哪个位置执行,hai可以让目标方法不执行@Around("myPointCut()")public Object aroundAspect(ProceedingJoinPoint point){System.out.println("----环绕前,around进行增强处理----");try {return point.proceed(point.getArgs());} catch (Throwable e) {// TODO Auto-generated catch blocke.printStackTrace();}System.out.println("----环绕后,around进行增强处理----");return null;}
}
>aop 查看目标方法相关信息
以Before增强处理为例:
/*** RepairAspect 切面类:增强处理类**/
@Aspect
public class RepairAspect {//配置切入点@Pointcut("execution(* com.langsin.dao.impl.*.*(..))")public void myPointCut(){}// 进行before增强处理的方法@Before("myPointCut()")public void beforeAspect(JoinPoint point) {//想看看目标方法的一些信息? 通过连接点JoinPoint//获取目标方法的执行参数列表System.out.println(Arrays.toString(point.getArgs()));//获取目标方法的对象System.out.println(point.getTarget());//获取目标方法的方法签名System.out.println(point.getSignature().getName());System.out.println("----目标方法执行之前,Before进行增强处理----");}
}
除此之外,如果只要看参数,Spring还提供了另外一种更为简洁的方式:
/*** RepairAspect 切面类:增强处理类**/
@Aspect
public class RepairAspect {//配置切入点,&& args(userId),对切入点表达式增加了额外的限制@Pointcut("execution(* com.langsin.dao.impl.*.*(..))&& args(userId)")public void myPointCut(Integer userId){}// 进行before增强处理的方法@Before("myPointCut(userId)")public void beforeAspect(JoinPoint point,Integer userId) {System.out.println(userId);System.out.println("----目标方法执行之前,Before进行增强处理----");}}
Spring AOP(面向切面编程)相关推荐
- Java绝地求生—Spring AOP面向切面编程
Java绝地求生-Spring AOP面向切面编程 背景 动态代理 构建被代理对象 自动生成代理 调用动态代理 Spring方法 方式一:使用Spring的API接口 方式二:使用自定义类 方式三:使 ...
- Spring AOP面向切面编程
AOP面向切面编程: AOP(Aspect Oriented Programming),即面向切面编程,它利用一种称为"横切"的技术,剖解开封装的对象内部,并将那些影响了多个类的公 ...
- Spring AOP 面向切面编程相关注解
Aspect Oriented Programming 面向切面编程 在Spring中使用这些面向切面相关的注解可以结合使用aspectJ,aspectJ是专门搞动态代理技术的,所以比较专业. 需要在 ...
- Spring Aop面向切面编程自动注入
1.面向切面编程 在程序原有纵向执行流程中,针对某一个或某一些方法添加通知,形成横切面的过程叫做面向切面编程 2.常用概念 原有功能:切点,pointcut 前置通知:在切点之前执行的功能,befor ...
- Spring AOP 面向切面编程
AOP 在软件业,AOP为Aspect Oriented Programming的缩写,意为:面向切面编程,通过预编译方式和运行期动态代理实现程序功能的统一维护的一种技术.AOP是OOP的延续,是软件 ...
- java框架013——Spring AOP面向切面编程
一.Spring AOP简介 AOP的全称是Aspect-Oriented Programming,即面向切面编程(也称面向方面编程).它是面向对象编程(OOP)的一种补充,目前已成为一种比较成熟的编 ...
- JavaEE——Spring AOP(面向切面编程)
目录 1.面向切面编程(AOP) 2.AOP术语 3.AOP类型 4.AOP 的优势 5.Spring AOP 的代理机制 6.Spring AOP 连接点 7.Spring AOP 通知类型 8.基 ...
- Spring AOP面向切面编程:理解篇(一看就明白)
一直想着怎么去通俗的讲解AOP,看了一篇文章受到了启发(https://blog.csdn.net/qukaiwei/article/details/50367761),下面我加入自己的理解,咱们来说 ...
- Spring aop面向切面编程概述
aop概述 1.AOP为Aspect Oriented Programming的缩写,意为:面向切面编程.将程序中公用代码进行抽离,通过动态代理实现程序功能的统一维护的一种技术.使代码耦合性降低,提高 ...
最新文章
- shell的各种运行模式?
- Proteus原理图元器件库详细说明
- 机器学习应用方向(二)~概念漂移(concept drift)
- POJ - 1381 Secret Code(dfs+高斯整数)
- POJ3277(矩形切割)
- 葡萄城报表V11 SP2新版本震撼发布!
- redis 一般启动几个 哨兵_Redis6.0主从、哨兵、集群搭建和原理
- Eigen入门之密集矩阵 6 - Reductions, visitors and broadcasting
- php mysql 图像_php-向/从MySQL数据库插入/查看图像
- 【技术分享】几维安全CTO刘柏江:IoT时代LLVM编译器防护的艺术
- JSONSerializer把类转换成JSON字符串
- php 去除零宽度空格,如何在PHP变量中去除空格?
- Unity使用Newtonsoft报错的解决方案
- html幻灯片滚动效果,jQuery实现全屏幻灯片的滚动页面效果
- root + vm vh 实现响应式字体
- 51定时器PWM调节
- 【迪文屏】踩坑指南——汉字显示乱码、背景图不显示问题的解决方法
- excel单元格内容拆分_EXCEL批量拆分单元格,也可以这么快
- 失语者的狂欢,觉醒者的自焚 ——《杀生》影评
- Qt5.4.1 + VS2008 环境搭建