Spring学习-AOP

前言

这部分内容基于Spring实战第四版,讲述Spring中面向切面编程的使用。

术语介绍

通知:
切面的工作被称为通知,通知定义了切面是什么以及何时使用,某个方法调用之前或调用之后。
Spring切面可以应用5种类型的通知:
前置通知;
后置通知;
返回通知;
异常通知;
环绕通知;
连接点:
连接点事在应用执行过程中能够插入切面的一个点。这个点可以是调用方法时,抛出异常时,甚至是修改一个字段时。切面代码可以利用这些点插入到应用的正常流程中,并添加新的行为。
切点:
切点定义了何处插入一个切面(我理解为连接点的子集)。切点的定义会匹配通知所要织入的一个或多个连接点。
切面:
切面是通知和切点的结合。通知和切面定义了切面的全部内容。
引入:
引入允许我们向现有类添加新方法或属性。
织入:
织入是吧切面应用到目标对象并创建新的代理对象的过程,切面在指定的连接点被织入到目标对象中。在目标对象的生命周期里有多个点可以进行织入:

  • 编译期:切面在目标类编译时被织入,这种方式需要特殊的编译器,AspectJ的织入编译器就是这种方式
  • 类加载期间:切面在目标类加载到JVM时被织入,这种方式需要特殊的类加载器,它可以在目标类被引入应用之前增强该目标类的字节码。AspectJ5支持这种方式。
  • 运行期:切面在应用程序运行的某个时刻织入,一般情况下,在织入切面时,AOP容器会为目标对象动态的创建一个代理对象SpringAOP就是以这种方式织入切面的。

Spring中的AOP

并不是所有AOP框架都是相同的,它们在连接点模型上可能有强弱之分,有些可以在字段修饰符级别应用通知,而另一些只支持方法调用相关的连接点。它们织入切面的方式和时机也有所不同,但无论如何,创建切点来定义切面所织入的连接点是AOP框架的基本功能。
Spring提供了四种AOP支持:

  • 基于代理的经典Spring’AOP
  • 纯POJO切面
  • @AspectJ注解驱动的切面
  • 注入式AspectJ切面

前三种都是SpringAOP实现的变体,SpringAOP构建在动态代理的基础之上。
*注:Spring只支持方法级别的连接点。

Spring借鉴了AspectJ。下面是SpringAOP所支持的AspectJ切点指示器。
这里写图片描述
同时,Spring还引入了一个新的Bean()指示器,它允许我们在切点表达式中使用Bean的ID来标识Bean。
定义切点表达式

开启自动代理

如果使用XML的Bean配置方式,那么需要使用Spring aop命名空间中的元素,这样你才能使用@AspectJ注解

<!--头需要添加Spring aop的命名空间-->
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/SMLSchema-instance"
    xmlns:context="http://www.springframework.org/schema/context"
    xmlns:aop="http://www.springframework.org/schema/aop"
    xsi:schemaLocation="http://www.springframework.org/schema/aop
        http://www.springframework.org/schema/aop/spring-aop.xsd
        http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context.xsd">
    <context:somponent-scan base-package="concert" />

    <!--启用AspectJ代理-->
    <aop:aspectj-autoproxy />

    <bean class="concert.Aaudience" />  
    >
</beans>

使用注解定义切面

假设我们已经定义了一个Performance类,它有个perform方法

@AspectJ
public class Audience {
    @Before("execution(** concert.Performance.perform(..))")
    public void silenceCellPhones(){
    System.out.println("silencing cell phones");
    }
}

Audience类使用@AspectJ注解标注,声明它为一个切面。
进一步使用注解可为Audience定义切面的行为。

  • @before 通知方法会在目标方法调用前执行
  • @After 通知方法会在目标方法返回或抛出异常后执行
  • @AfterReturning 通知方法会在目标方法返回后执行
  • @AfterThrowing 通知方法会在目标方法抛出异常后执行
  • @Around 使用比较特殊

@Pointcut定义切点

//在标注了@AspectJ类中使用下面代码,可以定义一个可重用的切点
@Pointcut("wxwcution(** concert.Performance.perform(..))")
public void performance(){}//这个方法内部不需要代码,实际上它只是用来标记切点。

//使用上面定义的切点
@After("performance()")
public void applause(){
...
}

@Around环绕通知
使用这个注解可以将目标方法完全包装起来,使用它需要在通知方法中添加一个ProceedingJoinPoint类型的参数,并在通知方法中执行这个参数的proceed(0方法(类似JVM动态代理的invoke方法)

@Around("performance()")
public void watchPerformance(PeoceedingJoinPoint jp) {
try{
    System.out.println("Silencing cell phones");
    jp.proceed();//此时执行目标方法
    System.out.println("CLAP CLAP CLAP");
} catch (Exception e) {
    System.out.println("Demanding a refund");
}
}

准备先研究SpringMVC的原理。。。待续

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值