spring学习(十八)--AOP切面编程

不同于OOP--面向对象编程,提供一系列继承、重写、封装技术,纵向的丰富编程功能。spring AOP为面向横向的切面编程,当工程中很多类都有共同的需求时,可以针对这些类,将共用的方法抽离出来,形成一个切面方法,将他织入到这些类中。每当执行这些类的时候,自动触发织入的切面方法,这样就不用在这些类中写重复的代码。

一 AOP的基本概念

(1)Aspect(切面):通常是一个类,里面可以定义切入点和通知

(2)JointPoint(连接点):程序执行过程中明确的点,一般是方法的调用

(3)Advice(通知):AOP在特定的切入点上执行的增强处理,有before,after,afterReturning,afterThrowing,around

(4)Pointcut(切入点):就是带有通知的连接点,在程序中主要体现为书写切入点表达式

(5)AOP代理:AOP框架创建的对象,代理就是目标对象的加强。Spring中的AOP代理可以使JDK动态代理,也可以是CGLIB代理,前者基于接口,后者基于子类

二 Spring AOP

Spring中的AOP代理还是离不开Spring的IOC容器,代理的生成,管理及其依赖关系都是由IOC容器负责,Spring默认使用JDK动态代理,在需要代理类而不是代理接口的时候,Spring会自动切换为使用CGLIB代理,不过现在的项目都是面向接口编程,所以JDK动态代理相对来说用的还是多一些。

AOP有两种实现方式,一种基于XML配置,一种基于注解,本篇先写一个基于XML配置的例子,下篇中讲解基于注解的AOP编程。

spring学习(十八)--AOP切面编程

 1、在spring中使用AOP变成,不止要导入spring-aop.jar,还需要导入spring-aspects.jar、aspectjweaver.jar和aopalliance.jar,但是aspectjweaver.jar被spring-aspects.jar依赖,aopalliance.jar被spring-aop.jar依赖,spring-aop.jar又被spring-mvc.jar依赖,所以只要导入spring-mvc.jar和spring-aspects.jar就行了。

pom.xml文件:

<properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <spring.version>4.0.5.RELEASE</spring.version>
  </properties>

  <dependencies>
  
  <!-- springMvc框架,它依赖于spring的其他jar包,会自动导入spring的core、beans、web等jar包 -->
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-webmvc</artifactId>
        <version>${spring.version}</version>
    </dependency>
    
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-aspects</artifactId>
        <version>${spring.version}</version>
    </dependency>

2、编写被增强的类,即被织入切面的类LittleBallImpl.java:

package springAop;

public class LittleBallImpl {
    
    /* 
     * 需要aop代理的方法
     * getLittleBallName()
     */
    public void getLittleBallName(String name){
        
        System.out.println("hello, I am little ball!");
    }
}

3、编写方法执行前、执行后、执行前后的增强类PrintDate.java、PrintWeather.java、AroundPoint.java,其中PrintDate通过在切入方法入参中添加JointPoint来获取被切方法的入参:

package springAop;

import java.util.Date;
import org.aspectj.lang.JoinPoint;

/**
 * 切面类
 * @author qiaozhong
 */
public class PrintDate {

    /**
     * 织入的具体业务方法,实现业务逻辑
     * JointPoint可获得被切的方法的入参
     */
    public void printDate(JoinPoint joinPoint){
        //获取被切的方法的入参
        Object[] o=joinPoint.getArgs();
        
        System.out.println(String.valueOf(o[0]) + new Date());
    }
}
package springAop;


public class PrintWeather {

    /**
     * 织入的具体业务方法,实现业务逻辑
     */
    public void printWeather(){
        System.out.println("Today is sunny");
    }
}
package springAop;

import org.aspectj.lang.ProceedingJoinPoint;

public class AroundPoint {
    /*
     * 环绕通知
     * */
    public void aroundPrint(ProceedingJoinPoint point) throws Throwable {
        System.out.println("环绕通知前。。。。。");
        point.proceed();
        System.out.println("环绕通知后。。。。。。");
    }
}

4、配置切面的配置文件spring-aop.xml,要加入aop相关的约束声明:

<?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-4.0.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd">
    <!-- 配置bean -->
    <bean id="littleBall" class="springAop.LittleBallImpl"></bean>
    <!-- 配置切面的bean -->
    <bean id="printDate" class="springAop.PrintDate"></bean>    
    <bean id="printWeather" class="springAop.PrintWeather"></bean>
    <bean id="aroundPoint" class="springAop.AroundPoint"></bean>

    <!-- 配置AOP -->
    <aop:config>
        <!-- 配置切面和通知  order:优先级,越小优先级越高-->
        <aop:aspect id="date" ref="printDate" order="1">
        <!-- 配置切面表达式 -->
        <aop:pointcut id="addDate" expression="execution(* springAop.LittleBallImpl.get*(..))" />
            <!-- 配置切面方法 -->
            <aop:before method="printDate" pointcut-ref="addDate"/>
            <aop:after method="printDate" pointcut-ref="addDate"/>
        </aop:aspect>
        
        <!-- 配置切面和通知  order:优先级,越小优先级越高-->
        <aop:aspect id="weather" ref="printWeather" order="2">
        <!-- 配置切面表达式 -->
        <aop:pointcut id="addWeather" expression="execution(* springAop.LittleBallImpl.get*(..))" />
            <!-- 配置切面方法 -->
            <aop:before method="printWeather" pointcut-ref="addWeather"/>
            <aop:after method="printWeather" pointcut-ref="addWeather"/>
        </aop:aspect>
        
        <!-- 配置切面和通知  order:优先级,越小优先级越高-->
        <aop:aspect id="aroundP" ref="aroundPoint" order="3">
        <!-- 配置切面表达式 -->
        <aop:pointcut id="aPoint" expression="execution(* springAop.LittleBallImpl.get*(..))" />
            <!-- 配置切面方法 -->
            <aop:around method="aroundPrint" pointcut-ref="aPoint"/>
        </aop:aspect>
    </aop:config>
</beans>

5、编写测试类TestAop.java:

package springAop;

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

public class TestAop {

    public static void main(String[] args) {
        ApplicationContext ac = new ClassPathXmlApplicationContext("springConfig/spring-aop.xml");
        LittleBallImpl littleBallImpl = (LittleBallImpl)ac.getBean(LittleBallImpl.class);
        littleBallImpl.getLittleBallName("hello ,I am little ball! Today is ");
    }
}

测试结果:

hello ,I am little ball! Today is Thu Oct 31 14:35:43 CST 2019
Today is sunny
环绕通知前。。。。。
hello, I am little ball!
环绕通知后。。。。。。
Today is sunny
hello ,I am little ball! Today is Thu Oct 31 14:35:43 CST 2019

结果分析:

1、先执行了addDate切面方法,通过JointPoint获取了被切方法的入参“hello ,I am little ball! Today is”

2、执行了addWeather切面方法

3、执行AroundPoint切面前置方法

4、执行业务类LittleBallImpl

5、执行AroundPoint切面后置方法

6、执行了addWeather切面方法

7、执行了addDate切面方法,通过JointPoint获取了被切方法的入参“hello ,I am little ball! Today is”

相关推荐