《Spring实战》(二)AOP

277 阅读3分钟

推荐:廖雪峰的官网网站:使用AOP

1.AOP术语

  • 通知(advice):描述切面要完成的工作,并何时执行这个工作。

    spring切面可以应用5种类型的通知:

    • 前置通知(Before):在目标方法被调用之前调用通知功能。
    • 后置通知(After):在目标方法完成之后调用通知,此时不会关心方法的输出是什么。
    • 返回通知(After-returning):在目标方法成功执行之后调用通知。
    • 异常通知(After-throwing):在目标方法抛出异常后调用通知;
    • 环绕通知(Around):通知包裹了目标方法,在目标方法调用之前和之后执行自定义的行为。
  • 连接点(joinpoint):在应用执行过程中能够插入切面的一个点。

  • 切点(pointcut):切点定义了在何处使用切面。

  • 切面(aspect):切面是通知和切点的结合,包括是什么、在何时、何处完成其工作。

  • 引入(Introduction):向现有的类添加新方法或属性。通过引入,可以在无需修改现有类的情况下,让它们具有新的行为和状态。

  • 织入(Weaving):织入是把切面应用到目标对象并创建新的代理对象的过程。在目标对象的生命周期中有多个点可以进行织入:

    • 编译期:切面在目标类编译时被织入。这种方式需要特殊的编译器,如:AspectJ的织入编译器
    • 类加载期:切面在目标类加载到JVM时被织入。这种方式需要特殊的类加载器,它可以在目标类被引入应用前增强其字节码,如:AspectJ 5的加载时织入(load-time weaving,LTW)
    • 运行期:切面在应用运行的某个时刻被织入。一般情况下,在织入切面时,AOP容器会为目标对象动态创建一个代理对象,如SpringAOP.

2.Spring对AOP的支持

  • Spring AOP基于动态代理构建,因此,Spring对AOP的支持局限于方法拦截。
  • Spring在运行时通知对象

下面以演出和观众来演示Spring AOP的使用方式。

1、定义要使用切面的目标类:

package concert;
public interface Performance {
  public void perform();
}

2、编写切点

使用切点表达式编写切点。下面展示了在perform()方法执行时触发通知的调用:

3、创建切面

可以通过注解和xml两种方式创建切面。 AspectJ提供了5个注解来定义通知:

注解通知
@Before通知方法在目标方法调用之前执行
@After通知方法在目标方法返回或抛出异常后调用
@AfterReturning通知方法在目标方法返回后调用
@AfterThrowing通知方法在目标方法抛出异常后调用
@Around通知方法会将目标方法封装起来

(1)注解 使用注解@Aspect表明该类是个切面。

package concert;
import ...;

@Aspect
public class Audience {
    // @Pointcut注解定义一个可重用的切点。注解设置的值是个切点表达式。
    @Pointcut("execution(** concert.Performance.perform(..))")
    public void performance() {}
    
    @Before("performance()")
    public void takeSeats() {...}
    
    // 也可以直接在注解后面写切点表达式
    @AfterReturning("execution(** concert.Performance.perform(..))")
    public void applause() {...}
    
    @Around("performance()")
    public void watchPerformance(ProceedingJoinPoint jp) {
      System.out.println("do something before...");
      // 调用被通知的方法
      jp.proceed();
      System.out.println("do something after.");
    }
}

启动自动代理:只有启用了自动代理,才能解析切面相关的注解,并创建对应切面的代理 在配置类上使用@EnableAspectJAutoProxy启用自动代理功能:

@Configuration
@EnableAspectJAutoProxy
@ComponentScan
public class ConcertConfig {
  @Bean
  public Audience audience() {
    return new Audience();
  }
}

(2)xml 启动自动代理: 使用spring aop命名空间中的<aop:aspectj-autoproxy>元素启用自动代理功能:

<aop:aspectj-autoproxy />

3.引入

通过引入,可以为Spring bean添加新方法。