Spring学习03--AOP基础知识和常规用法
AOP常用术语
通知(Advice):切面的工作被称为通知。它定义了“何时”、“怎样”的概念。Spring切面可以应用5种类型的通知
- 前置通知(Before):在目标方法被调用之前调用通知功能。
- 后置通知(After):在目标方法完成之后调用通知,不关心方法的输出是什么
- 返回通知(After-returning):在目标方法成功执行之后调用通知
- 异常通知(After-throwing):在目标方法抛出异常后调用通知
- 环绕通知(Around):通知包裹了目标方法,在被调用之前和调用之后执行自定义的行为
连接点(Join point):切面插入应用执行过程的时机,可以是调用发放时,可以是抛出异常时,
甚至是修改一个字段时。 - 切点(Pointcut):通知织入的一个或多个连接点。
- 切面(Aspect):通知和切点的结合。在何时(Advice)何处(Joincut)完成怎样(Advice)的动作
- 引入(Introdction):在不修改现有类的情况下,向现有的类添加新方法或属性。
- 织入(Weaving):把切面应用到目标对象并创建新的代理对象的过程。切面在指定的连接点被织入到目标对象中。在目标对象的生命周期里有多个点可以进行织入:
#编译期:切面在目标类编译时被织入。这种方式需要特殊的编译器。AspectJ的织入编译器就是以这种方式实现。
#类加载期:切面在目标类加载到JVM时被织入。
#运行期:切面在应用运行的每个时刻被织入。一般情况下,切面在织入时,AOP容器会为目标对象动态地创建一个代理对象。SpringAOP就是以这种方式织入
Spring提供了4种类型的SpringAOP支持:
1.基于经典的SpirngAOP
2.纯POJO切面
3.@AspectJ注解驱动的切面
4.注入式AspectJ切面
看完了上面AOP相关基础知识,接下来实际看一下代码中AOP的应用。假定一个场景,某舞团来我市进行一场表演
//表演可能是现代舞表演,可能是民族舞表演等等... public interface Performance{ public void perform(); }
表演快开始了,观众进场。1.观众找到自己的位置就做;2.观众很有素质,把手机调成了静音。(不管是什么表演,观众就做和手机静音两项是不是都需要完成的,而跟什么表演无关),这是不是很符合AOP的使用场景,所以我们创建一个观众类Audience,并给它添加上就坐takeseats和给手机静音siliencePhones两个方法。
public class Audience{ public void takeSeats(){ System.out.println("Taking seats"); } public void sliencePhone(){ System.out.println("Sliencing cellPhones"); } }
Audience只是一个普通JOPO类,我们用注解的方式来实现这个切面
@Aspect public class Audience{ @Before("execution(** Perforence.perform(..))") public void takeSeats(){ System.out.println("Taking seats"); } @Before("execution(** Perforence.perform(..))") public void sliencePhone(){ System.out.println("Sliencing cellPhones"); } }
如上,@Aspect表示该类作为切面使用,@Before声明为前置通知,execution(** Perforence.perform(…))为ES6的语法,声明切点。但到此为止Audience仍然只会是Spring容器中的一个bean,即便有了@Aspect注解,它也不睡被视为切面,为了创建将其转换为切面的代理,下面我们通过Java配置的方式来实现。
@Configuration @EnableAspectJAutoProxy @ComponentScan public class PerformanceConfig{ @Bean pulic Audience audience(){ return new Audience(); } }
@EnableAspectJAutoProxy注解功能为启用自动代理,生成Audience的代理类,织入目标类Perfomance中,拦截被通知方法perform的调用,执行切面逻辑,再把调用转发给目标bean(Performance);同理,接下来我们把后置通知@After,异常通知@After-throwing,返回通知@After-returnning,加入进来
@Aspect public class Audience{ @Before("execution(** Perforence.perform(..))") public void takeSeats(){//表演前 就座 System.out.println("Taking seats"); } @Before("execution(** Perforence.perform(..))") public void sliencePhone(){//表演前 手机静音 System.out.println("Sliencing cellPhones"); } @AfterReturnning("execution(** Perforence.perform(..))") public void applause(){//表演结束 鼓掌 System.out.println("CLAP CLAP CLAP!!!"); } @AfterThrowing("execution(** Perforence.perform(..))") public void demandRefund(){//表演失败 退款 System.out.println("Demanding a refund"); } }
仔细看上面的代码,发现execution(** Perforence.perform(…))被重复使用多次,可以优化一下,声明切点并通过引用来使用它
@Aspect public class Audience{ //声明切点 通过引用调用 @Pointcut("execution(** Perforence.perform(..))") public void performance(){} @Before("performance()") public void takeSeats(){//表演前 就座 System.out.println("Taking seats"); } @Before("performance()") public void sliencePhone(){//表演前 手机静音 System.out.println("Sliencing cellPhones"); } @AfterReturnning("performance()") public void applause(){//表演结束 鼓掌 System.out.println("CLAP CLAP CLAP!!!"); } @AfterThrowing("performance()") public void demandRefund(){//表演失败 退款 System.out.println("Demanding a refund"); } }
一开始我们就说了又5种类型的通知,上面我们已经使用了4种类型的通知,还有最后一种还没有使用过——环绕通知@Around,与其他通知不同,环绕通知能够将被通知方法完全包裹起来。通过下面的例子我们来认识下环绕通知
@Aspect public class Audience{ @Pointcut("execution(** Perforence.perform(..))") public void performance(){} @Around("perfomance()") public void aroundPerform(ProceedingJoinPoint jp){ try{ System.out.println("Taking seats");//演出前-就坐 System.out.println("Sliencing cellPhones");//演出前-手机静音 jp.proceed();//调用被通知方法(perform)-演出中 System.out.println("CLAP CLAP CLAP!!!");//演出完成 -鼓掌 }catch(Throwable e){ System.out.println("Demanding a refund");//演出失败-退款 } }
可以看到@Around完全将目标方法包裹,类似于在一个方法中同时编写了前置/后置通知。
到目前为止我们所有的切面都很简单,都是没有带参数的。因为perform()方法本身不带参。如果通知带参呢,切面能访问和传递被通知方法的参数吗?
- 点赞
- 收藏
- 分享
- 文章举报
- SpringAop学习02:基础知识
- Spring AOP基础知识学习——XML配置
- 学习Spring必学的Java基础知识----反射
- 基础知识03 - 零基础入门学习汇编语言03
- 黑马程序员_java基础学习笔记03_函数以及数组知识
- Spring(基础)学习文档五(spring的aop详解)
- 学习Spring必学的Java基础知识(6)----ThreadLocal
- 学习Spring必学的Java基础知识(1)----反射
- 学习Spring必学的Java基础知识(2)----动态代理
- 学习Spring必学的Java基础知识----反射
- 学习Spring必学的Java基础知识(4)----XML基础知识
- 学习javascript基础知识系列第三节 - ()()用法
- 学习Spring必学的Java基础知识(1)----反射
- 学习Spring必学的Java基础知识(1)----反射
- spring学习。理解一些思想。记住一些常规用法
- Spring学习(四)---Spring Aop基础
- spring 学习(1.2) 入门基础- AOP
- 学习Spring必学的Java基础知识(1)----反射
- 学习spring应掌握的Java基础知识
- 学习Spring必学的Java基础知识(1)----反射