Spring AOP-00-开篇

1. 横切关注点

一些具有横切多个不同软件模块的行为,通过传统的软件开发方法不能够有效地实现模块化的一类特殊关注点。横切关注点可以对某些方法进行拦截,拦截后对原方法进行增强处理。

2. 切面(Aspect)

切面就是对横切关注点的抽象,这个关注点可能会横切多个对象。

3. 连接点(JoinPoint)

连接点是在程序执行过程中某个特定的点,比如某方法调用的时候或者处理异常的时候。由于Spring只支持方法类型的连接点,所以在Spring AOP中一个连接点总是表示一个方法的执行。

4. 切入点(Pointcut)

切入点是匹配连接点的拦截规则,在满足这个切入点的连接点上运行通知。切入点表达式如何和连接点匹配是AOP的核心,Spring默认使用AspectJ切入点语法。

5. 通知(Advice)

在切面上拦截到某个特定的连接点之后执行的动作。

6. 目标对象(Target Object)

目标对象,被一个或者多个切面所通知的对象,即业务中需要进行增强的业务对象。

7. 织入(Weaving)

织入是把切面作用到目标对象,然后产生一个代理对象的过程。

8. 引入(Introduction)

引入是用来在运行时给一个类声明额外的方法或属性,即不需为类实现一个接口,就能使用接口中的方法。

 

二、下面介绍增强的类型

AOP联盟为增强定义了org.aopalliance.aop.Advice接口,Spring支持5种类型的增强。以下显示用到的@Before、@After等注解是基于AspectJ实现的增强类型。其实Spring也支持很多增强类型,Spring AOP按照增强在目标类方法中的连接点位置可以分为5种。

• 前置增强(MethodBeforeAdvice):表示在目标方法执行前实施增强。

• 后置增强(AfterReturningAdvice):表示在目标方法执行后实施增强。

• 环绕增强(MethodInterceptor):表示在目标方法执行前后实施增强。

• 异常抛出增强(ThrowsAdvice):表示在目标方法抛出异常后实施增强。

• 引介增强(IntroductionInterceptor):表示在目标类中添加一些新的方法和属性。

AOP联盟的顶级接口是Advice,其类图如下:

三、用文字介绍概念太抽象了,以下用代码来表示各个概念

1、要增强的类

package com.test.aspectj.advicetype;

import org.springframework.stereotype.Component;

/**
 * 一个Spring Bean
 */
@Component
public class Person {

    /**
     * 说话的方法
     */
    public void say() {
        System.out.println("Hello spring5");
    }
}

2、切面类

package com.test.aspectj.advicetype;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;

/**
 * 包含各种增强类型的切面
 */
@Component
@Aspect
public class AllAspect {

    /**
     * 切入点
     */
    @Pointcut("execution(* com.test.aspectj.advicetype.*.*(..))")
    public void allAointCut() {

    }

    /**
     * 前置增强
     */
    @Before("allAointCut()")
    public void before() {
        System.out.println("before advice");
    }

    /**
     * 环绕增强
     * @param proceedingJoinPoint
     */
    @Around("allAointCut()")
    public void around(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
        System.out.println("around advice 1");
        proceedingJoinPoint.proceed();
        System.out.println("around advice 2");
    }

    /**
     * 后置增强
     */
    @AfterReturning("allAointCut()")
    public void afterReturning() {
        System.out.println("afterReturning advise");
    }

    /**
     * 异常抛出增强
     */
    @AfterThrowing("allAointCut()")
    public void afterThrowing() {
        System.out.println("afterThrowing advice");
    }

    /**
     * 后置增强
     */
    @After("allAointCut()")
    public void after() {
        System.out.println("after advise");
    }
}

3、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"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
       http://www.springframework.org/schema/aop 
http://www.springframework.org/schema/aop/spring-aop.xsd http://www.springframework.org/schema/context 
http://www.springframework.org/schema/context/spring-context.xsd">
    <!-- 开启注解扫描 -->
    <context:component-scan base-package="com.test.aspectj.advicetype"/>
    <!-- 开启aop注解方式,此步骤不能少 -->
    <aop:aspectj-autoproxy/>
</beans>

4、测试代码

package com.test.aspectj.advicetype;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

/**
 * 测试各种类型的增强
 */
public class AllAspectDemo {

    public static void main(String[] args) {
        ApplicationContext context = new ClassPathXmlApplicationContext("classpath:spring-chapter3-aoptype.xml");
        Person person = (Person) context.getBean("person");
        person.say();
    }
}

5、运行结果

around advice 1
before advice
Hello spring5
around advice 2
after advise
afterReturning advise