Spring学习笔记|二、面向切面编程(AOP)

文章目录

    • 一、AOP简介
    • 二、AOP常用术语
    • 三、AOP实现
      • 1、写一个正常的面向对象类
      • 2、添加AOP
        • 2.1、注解定义切面
          • ① 首先先配置XML
          • ② 然后添加切面类
          • ③ 测试代码
          • ④ 总结
        • 2.2、XML定义切面
        • 2.3、Spring API实现

一、AOP简介

面向方面的编程(Aspect-oriented Programming,简称AOP)通过提供另一种思考程序结构的方式来补充面向对象的编程(OOP)。这是官方文档对AOP定义的翻译,看不懂没关系,先实现一个简单的Demo,再回过头思考什么是AOP会容易很多。

二、AOP常用术语

Name Description
通知(Advice) 切面的工作内容
连接点(Joint point) 切点通知的时机
切点(Point cut) 在何处通知
切面(Aspect) 通知和切点的结合(切点是什么,在何时和何处完成通知)
引入(Introduction) 向现有的类添加新方法或新属性
织入(Weaving) 把切面应用到目标对象并创建新的代理对象的过程

同样的,暂时看不懂没关系,通过一个简单的Demo可以很容易理解!

三、AOP实现

这里用的例子是参考《Spring实战(第四版)》里面的例子,我模仿书里面的代码后不能运行,所以做了一些修改。

1、写一个正常的面向对象类

设计一个表演的场景。表演的接口类和表演的实现类。

package com.kai.service;
public interface Performance {
    public void perform();
}
package com.kai.service;
public class PerformanceImpl implements Performance {
    public void perform(){
        System.out.println("Performance接口实现!");
    }
}

测试代码:

import com.kai.service.Performance;
import com.kai.service.PerformanceImpl;

public class MyTest {
    public static void main(String[] args) {
        PerformanceImpl performance = new PerformanceImpl();
        performance.perform
    }
}

这样就实现了一个表演的场景,但是现实中的表演场景明显会更加复杂,在表演开始前,为表示礼貌手机需要静音、然后搬个板凳,表演结束后要鼓掌。但是现在表演类已经写好了,怎么把这些功能加进去而不影响原来的代码呢?这就用到面向切面编程(AOP)了。

2、添加AOP

AOP的实现方法有三种:①Spring API实现;②XML定义切面;③注解定义切面。因为很多书还有网上教程都没说明是用哪种方法,所以相互参考的时候搞的有点懵,走了一些弯路。

2.1、注解定义切面

注解实现应该是最简单的方法了。

① 首先先配置XML

<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"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        https://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/aop
        https://www.springframework.org/schema/aop/spring-aop.xsd">

    <bean id="performance" class="com.kai.service.PerformanceImpl"/>
    <bean id="audience" class="com.kai.log.Audience"/>
    <aop:aspectj-autoproxy/>

beans>

基于注解的AOP实现配置XML非常简单,只需要加入自动代理支持就行了。

② 然后添加切面类
package com.kai.log;

import org.aspectj.lang.annotation.*;

@Aspect
public class Audience {
    @Pointcut("execution(* com.kai.service.PerformanceImpl.perform(..))")
    public void performance(){}

    @Before("performance()")			// 表演之前
    public void silenceCellPhone() {
        System.out.println("Silence cell phones.");
    }

    @Before("performance()")			// 表演之前
    public void takeSeat() {
        System.out.println("Taking Seats.");
    }

    @AfterReturning("performance()")	// 表演之后
    public void applause() {
        System.out.println("CLAP CLAP CLAP!!!");
    }

    @AfterThrowing("performance()")		// 表演失败之后
    public void demandfund() {
        System.out.println("Demanding a refund.");
    }
}
③ 测试代码
import com.kai.service.Performance;
import com.kai.service.PerformanceImpl;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class MyTest {
    public static void main(String[] args) {
        ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
        Performance performance = (Performance) context.getBean("performance");
        performance.perform();
    }
}

运行结果:
Spring学习笔记|二、面向切面编程(AOP)_第1张图片

④ 总结

从运行结果可以看出,加入Audience类之后,在perform()方法之前先执行了silenceCellPhone()takeSeat()方法,在perform()方法执行结束之后又执行了applause方法。看到这应该可以理解面向切面编程是什么意思了吧。通俗地讲就是在原来的代码基础上切入一些功能。

再来看下Audience类,@Aspect注解声明这个类是一个切面@Pointcut注解声明了切点的位置,这里既Perform()方法,我们需要在Perform()方法前后添加功能,所以它就是切点。@Before@AfterReturning@AfterThrowing这三个注解则定义了添加的功能的内容,这个内容就是通知连接点则是定义的Performace接口。几个术语一下子就搞定了。

2.2、XML定义切面

顾名思义,上一种方式是通过注解来定义切面,因此在XML中只需要加入自动代理即可。这种方法则需要在XML手动定义切面。还是以上面那个例子来介绍。

表演的接口和实现类不变,修改下Audience类:

package com.kai.log;

import org.aspectj.lang.annotation.*;

public class Audience {

    public void silenceCellPhone() {
        System.out.println("Silence cell phones.");
    }

    public void takeSeat() {
        System.out.println("Taking Seats.");
    }

    public void applause() {
        System.out.println("CLAP CLAP CLAP!!!");
    }

    public void demandfund() {
        System.out.println("Demanding a refund.");
    }
}

也就是将注解删掉,将切面的定义转移到XML文件中。XML配置文件:


<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"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        https://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/aop
        https://www.springframework.org/schema/aop/spring-aop.xsd">

    <bean id="performance" class="com.kai.service.PerformanceImpl"/>
    <bean id="audience" class="com.kai.log.Audience"/>

    <aop:config>
        <aop:aspect ref="audience">
            
            <aop:pointcut id="pointcut" expression="execution(* com.kai.service.PerformanceImpl.perform(..))"/>
            
            <aop:before method="silenceCellPhone" pointcut-ref="pointcut"/>
            <aop:before method="takeSeat" pointcut-ref="pointcut"/>
            <aop:after-returning method="applause" pointcut-ref="pointcut"/>
            <aop:after-throwing method="demandfund" pointcut-ref="pointcut"/>
        aop:aspect>
    aop:config>
beans>

可以看到相比于注解的方式,这种方式使得配置文件的内容多了很多。

2.3、Spring API实现

这种方法比较复杂,现在已经渐渐被淘汰了,这里就不多做介绍,有兴趣可以去B站看秦疆老师的视频。

主要参考材料

  1. Spring5最新完整教程IDEA版【通俗易懂】
  2. 《Spring实战(第四版)》
  3. 什么是面向切面编程AOP?

Tips:

本人是刚开始学习Sping,如有错误或者不足之处还望不吝赐教,欢迎共同交流学习!

你可能感兴趣的:(Spring学习笔记)