转自:http://blog.csdn.net/a906998248/article/details/7514969
一、什么是 AOP。
AOP(Aspect Orient Programming),也就是面向切面编程。可以这样理解,面向对象编程(OOP)是从静态角度考虑程序结构,面向切面编程(AOP)是从动态角度考虑程序运行过程。
二、AOP 的作用。
常常通过 AOP 来处理一些具有横切性质的系统性服务,如事物管理、安全检查、缓存、对象池管理等,AOP 已经成为一种非常常用的解决方案。
三、AOP 的实现原理。
如图:AOP 实际上是由目标类的代理类实现的。AOP 代理其实是由 AOP 框架动态生成的一个对象,该对象可作为目标对象使用。AOP 代理包含了目标对象的全部方法,但 AOP 代理中的方法与目标对象的方法存在差异,AOP 方法在特定切入点添加了增强处理,并回调了目标对象的方法。
四、Spring 中对 AOP 的支持
Spring 中 AOP 代理由 Spring 的 IoC 容器负责生成、管理,其依赖关系也由 IoC 容器负责管理。因此,AOP 代理可以直接使用容器中的其他 Bean 实例作为目标,这种关系可由 IoC 容器的依赖注入提供。Spring 默认使用 Java 动态代理来创建 AOP 代理, 这样就可以为任何接口实例创建代理了。当需要代理的类不是代理接口的时候, Spring 自动会切换为使用 CGLIB 代理,也可强制使用 CGLIB。
AOP 编程其实是很简单的事情。纵观 AOP 编程, 其中需要程序员参与的只有三个部分:
- 定义普通业务组件。
- 定义切入点,一个切入点可能横切多个业务组件。
- 定义增强处理,增强处理就是在 AOP 框架为普通业务组件织入的处理动作。
所以进行 AOP 编程的关键就是定义切入点和定义增强处理。一旦定义了合适的切入点和增强处理,AOP 框架将会自动生成 AOP 代理,即:代理对象的方法 = 增强处理 + 被代理对象的方法。
五、Spring 中 AOP 的实现。
Spring 有如下两种选择来定义切入点和增强处理。
- 基于 Annotation 的“零配置”方式:使用@Aspect、@Pointcut等 Annotation 来标注切入点和增强处理。
- 基于 XML 配置文件的管理方式:使用 Spring 配置文件来定义切入点和增强点。
1、基于 Annotation 的“零配置”方式。
(1)、首先启用 Spring 对 @AspectJ 切面配置的支持。
- <?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-3.0.xsd
- http://www.springframework.org/schema/aop
- http://www.springframework.org/schema/beans/spring-aop-3.0.xsd">
- <!-- 启动对@AspectJ注解的支持 -->
- <aop:aspectj-autoproxy/>
- </beans>
如果不打算使用 Spring 的 XML Schema 配置方式,则应该在 Spring 配置文件中增加如下片段来启用@AspectJ 支持。
- <!-- 启用@AspectJ 支持 -->
- <bean class="org.springframeword.aop.aspectj.annotation.AnnotationAwareAspectJAutoProxyCreator" />
(2)、定义切面 Bean。
当启动了@AspectJ 支持后,只要在 Spring 容器中配置一个带@Aspect 注释的 Bean, Spring 将会自动识别该 Bean 并作为切面处理。
- // 使用@Aspect 定义一个切面类
- @Aspect
- public class LogAspect {
- // 定义该类的其他内容
- ...
- }
(3)、定义 Before 增强处理。
- // 定义一个切面
- @Aspect
- public class BeforeAdviceTest {
- // 匹配 com.wicresoft.app.service.impl 包下所有类的所有方法作为切入点
- @Before("execution(* com.wicresoft.app.service.impl.*.*(..))")
- public void authorith(){
- System.out.println("模拟进行权限检查。");
- }
- }
上面使用@Before Annotation 时,直接指定了切入点表达式,指定匹配 com.wicresoft.app.service.impl包下所有类的所有方法执行作为切入点。
关于这个表达式的规则如下图。
(4)、定义 AfterReturning 增强处理。
- // 定义一个切面
- @Aspect
- public class AfterReturningAdviceTest {
- // 匹配 com.wicresoft.app.service.impl 包下所有类的所有方法作为切入点
- @AfterReturning(returning="rvt", pointcut="execution(* com.wicresoft.app.service.impl.*.*(..))")
- public void log(Object rvt) {
- System.out.println("模拟目标方法返回值:" + rvt);
- System.out.println("模拟记录日志功能...");
- }
- }
(5)、定义 AfterThrowing 增强处理。
- // 定义一个切面
- @Aspect
- public class AfterThrowingAdviceTest {
- // 匹配 com.wicresoft.app.service.impl 包下所有类的所有方法作为切入点
- @AfterThrowing(throwing="ex", pointcut="execution(* com.wicresoft.app.service.impl.*.*(..))")
- public void doRecoverActions(Throwable ex) {
- System.out.println("目标方法中抛出的异常:" + ex);
- System.out.println("模拟抛出异常后的增强处理...");
- }
- }
(6)、定义 After 增强处理。
After 增强处理与AfterReturning 增强处理有点相似,但也有区别:
- AfterReturning 增强处理处理只有在目标方法成功完成后才会被织入。
- After 增强处理不管目标方法如何结束(保存成功完成和遇到异常中止两种情况),它都会被织入。
- // 定义一个切面
- @Aspect
- public class AfterAdviceTest {
- // 匹配 com.wicresoft.app.service.impl 包下所有类的所有方法作为切入点
- @After("execution(* com.wicresoft.app.service.impl.*.*(..))")
- public void release() {
- System.out.println("模拟方法结束后的释放资源...");
- }
- }
(7)、Around 增强处理
Around 增强处理近似等于 Before 增强处理和 AfterReturning 增强处理的总和。它可改变执行目标方法的参数值,也可改变目标方法之后的返回值。
- // 定义一个切面
- @Aspect
- public class AroundAdviceTest {
- // 匹配 com.wicresoft.app.service.impl 包下所有类的所有方法作为切入点
- @Around("execution(* com.wicresoft.app.service.impl.*.*(..))")
- public Object processTx(ProceedingJoinPoint jp) throws java.lang.Throwable {
- System.out.println("执行目标方法之前,模拟开始事物...");
- // 执行目标方法,并保存目标方法执行后的返回值
- Object rvt = jp.proceed(new String[]{"被改变的参数"});
- System.out.println("执行目标方法之前,模拟结束事物...");
- return rvt + "新增的内容";
- }
- }
(8)、访问目标方法的参数。
访问目标方法最简单的做法是定义增强处理方法时将第一个参数定义为 JoinPoint 类型,当该增强处理方法被调用时,该 JoinPoint 参数就代表了织入增强处理的连接点。JoinPoint 里包含了如下几个常用方法。
- Object[] getArgs(): 返回执行目标方法时的参数。
- Signature getSignature(): 返回被增强的方法的相关信息。
- Object getTarget(): 返回被织入增强处理的目标对象。
- Object getThis(): 返回 AOP 框架为目标对象生成的代理对象。
提示:当时使用 Around 处理时,我们需要将第一个参数定义为 ProceedingJoinPoint 类型,该类型是 JoinPoint 类型的子类。
(9)、定义切入点。
所谓切入点,其实质就是为一个切入点表达式起一个名称,从而允许在多个增强处理中重用该名称。
Spring 切入点定义包含两个部分:
- 一个切入点表达式。
- 一个包含名字和任意参数的方法签名。
- // 使用@Pointcut Annotation 时指定切入点表达式
- @pointcut("execution * transfer(..)")
- // 使用一个返回值为void,方法体为空的方法来命名切入点
- private void anyOldTransfer(){}
- // 使用上面定义的切入点
- @AfterReturning(pointcut="anyOldTransfer()", returning="reVal")
- public void writeLog(String msg, Object reVal){
- ...
- }
2、基于 XML 配置文件的管理方式。
- 不配置切入点
- <?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-3.0.xsd
- http://www.springframework.org/schema/aop
- http://www.springframework.org/schema/beans/spring-aop-3.0.xsd">
- <aop:config>
- <!-- 将 fourAdviceBean 转换成切面 Bean, 切面 Bean 的新名称为:fourAdviceAspect,指定该切面的优先级为2 -->
- <aop:aspect id="fourAdviceAspect" ref="fourAdviceBean" order="2">
- <!-- 定义个After增强处理,直接指定切入点表达式,以切面 Bean 中的 Release() 方法作为增强处理方法 -->
- <aop:after pointcut="execution(* com.wicresoft.app.service.impl.*.*(..))" method="release" />
- <!-- 定义个Before增强处理,直接指定切入点表达式,以切面 Bean 中的 authority() 方法作为增强处理方法 -->
- <aop:before pointcut="execution(* com.wicresoft.app.service.impl.*.*(..))" method="authority" />
- <!-- 定义个AfterReturning增强处理,直接指定切入点表达式,以切面 Bean 中的 log() 方法作为增强处理方法 -->
- <aop:after-returning pointcut="execution(* com.wicresoft.app.service.impl.*.*(..))" method="log" />
- <!-- 定义个Around增强处理,直接指定切入点表达式,以切面 Bean 中的 processTx() 方法作为增强处理方法 -->
- <aop:around pointcut="execution(* com.wicresoft.app.service.impl.*.*(..))" method="processTx" />
- </aop:aspect>
- </aop:config>
- <!-- 省略各个Bean 的配置 -->
- <!-- ... -->
- </beans>
- 配置切入点
- <?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-3.0.xsd
- http://www.springframework.org/schema/aop
- http://www.springframework.org/schema/beans/spring-aop-3.0.xsd">
- <aop:config>
- <!-- 定义一个切入点,myPointcut,直接知道它对应的切入点表达式 -->
- <aop:pointcut id="myPointcut" expression="execution(* com.wicresoft.app.service.impl.*.*(..))" method="release" />
- <aop:aspect id="afterThrowingAdviceAspect" ref="afterThrowingAdviceBean" order="1">
- <!-- 使用上面定于切入点定义增强处理 -->
- <!-- 定义一个AfterThrowing 增强处理,指定切入点以切面 Bean 中的 doRecovertyActions() 方法作为增强处理方法 -->
- <aop:after-throwing pointcut-ref="myPointcut" method="doRecovertyActions" throwing="ex" />
- </aop:aspect>
- </aop:config>
- <!-- 省略各个Bean 的配置 -->
- <!-- ... -->
- </beans>
参考:
《轻量级 Java EE 企业应用实战(第三版)》 李刚
相关推荐
3、对spring aop认识模糊的,不清楚如何实现Java 自定义注解的 4、想看spring aop 注解实现记录系统日志并入库等 二、能学到什么 1、收获可用源码 2、能够清楚的知道如何用spring aop实现自定义注解以及注解的逻辑...
spring aop jar 包
描述一下Spring AOP? 在Spring AOP中关注点(concern)和横切关注点(cross-cutting concern)有什么不同? AOP有哪些可用的实现? Spring中有哪些不同的通知类型(advice types)? Spring AOP 代理是什么? 引介...
基于注解实现SpringAop基于注解实现SpringAop基于注解实现SpringAop
死磕Spring之AOP篇 - Spring AOP两种代理对象的拦截处理(csdn)————程序
spring aop切面拦截指定类和方法实现流程日志跟踪 一般情况下,在不侵入业务代码的情况下,需要做流程日志跟踪是比较合理的 采用springaop切面思想
AOP的意思就是面向切面编程。本文主要是通过梳理JDK中自带的反射机制,实现 AOP动态代理模式,这也是Spring AOP 的实现原理
springaop依赖的jar包,spring版本2.5.6,如果需要,可以下载使用,欢迎各位评论指出不足
springAOP配置实现动态代理,有利于熟悉动态代理原理,深入了解spring。
Spring源码最难问题:当Spring AOP遇上循环依赖.docx
spring aop的demo spring aop的demo
Spring AOP 入门 作者:廖雪峰
spring aop spring aop spring aop spring aop spring aop spring aop spring aop spring aop spring aop
Spring AOP 日志管理 实例LoggingThrowsAdvice.java
Spring AOP 几个不同使用方法的完整例子,使用Junit4c测试, 在我的博客上有不同配置组合的说明,可以参考
Spring AOP的实现机制中文版,动态代理及原理,自定义类加载器
Spring AOP简单demo 入门级的 advice
springAOP详解
spring aop 经典例子(原创),无论新手还是老手,可以快速对Spring AOP有个总体的认识。基于JDK1.6,Spring2.0.5,Eclipse IDE。
springaop多数据库读写分离