声明:本博客仅仅是一个初学者的学习记录、心得总结,其中肯定有许多错误,不具有参考价值,欢迎大佬指正,谢谢!想和我交流、一起学习、一起进步的朋友可以加我微信Liu__66666666

这是简单学习一遍之后的记录,后期还会修改。

一、问题引入

​ 在日常写项目的时候,肯定少不了要打印日志。例如,要向数据库中insert一个用户,我想在插入前输出一下相关信息,怎么实现呢?最基本的做法是:在insert方法中写日志输出语句。这样写完全能实现功能,但是会不会显得很冗余?耦合度是不是很高?编程的准则是“高内聚,低耦合”,低耦合的意思就是类与类之间的依赖关系尽量少、关联程度尽量小。

​ 而如果在上述情景中使用面向切面编程(AOP),就可以不在insert方法中写日志输出语句却能实现日志输出功能。当然,AOP不止如此。

二、概念引入

1.AOP

在软件业,AOP为Aspect Oriented Programming的缩写,意为:面向切面编程,通过预编译方 式和运行期动态代理实现程序功能的统一维护的一种技术。AOP是OOP的延续,是软件开发中的一个 热点,也是Spring框架中的一个重要内容,是函数式编程的一种衍生范型。利用AOP可以对业务逻辑 的各个部分进行隔离,从而使得业务逻辑各部分之间的耦合度降低,提高程序的可重用性,同时提高 了开发的效率。

2.几个基本概念

- 切入点:所有要操作的方法定义,要求业务层方法风格统一 - 分离点:将不可分割的组件单独提取出去定义为单独的操作功能 - 横切关注点:将所有与开发无关的程序组成类单独提取后组织运行 - 织入:将所有切入点、关注点的代码组成在一张完整的程序结构中

3.通知(Advice)

​ AOP是通过通知来实现功能的,有如下五种:

  • 前置通知(BeforeAdvice)
  • 后置通知(AfterAdvice)

  • 后置返回通知(AfterReturningAdvice)
  • 后置异常通知(AfterThrowingAdvice)
  • 环绕通知(AroundAdvice)

三、Pointcut与Execution表达式

​ pointcut使用execution表达式表示要被切入的方法(即定义切入点)。

​ execution表达式,功能类似于正则表达式,都是用来匹配筛选,只不过正则表达式用来筛选字符串,而execution表达式用来筛选要被切入的方法。

​ execution表达式的格式为:

​ execution(<注解>? <修饰符>? <返回值类型> <方法名模式>(<参数模式>) <异常>?)) <and args()>?)

​ 例:execution(@Deprecated public Void aop.MyAspect.hello(int,String) throws Exception))')

package aop;  public class AspectDemo {   @Deprecated   public void hello(int i,String s) throws Exception{    } }

​ 其实不难发现,这个表达式和我们声明的方法的各个部分一一对应

  • 注解:(可省略)例如上面代码中的@Deprecated,就是筛选带有该注解的方法

  • 修饰符(可省略)

    • public
    • protected
    • private

    当然一般用通配符 *

  • 返回值类型

    写各种返回值,一般用通配符 *

  • 方法名模式

    • 包名部分:在上例中,AspectDemo是位于aop包中的,所以可以通过包名.包名.类名的格式来定位到某个类,例如aop.AspectDemo 中aop. 就是包名部分;

      当然也可以用通配符

      • *:匹配任何数量字符,例如service.*.UserService 表示的是service的直接子包
      • ..:匹配任何数量字符的重复,如在类型模式中匹配任何数量子包,例如service..代表着匹配service及其包含的所有包;而在方法参数模式中匹配任何数量参数。
      • +:匹配指定类型的子类型;仅能作为后缀放在类型模式后边,例如java.lang.Number+ 表示的是lang包下Numer的子类
    • 类名部分:在上例中aop.AspectDemo中aop.是包名部分,AspectDemo就是类名部分,可以用通配符来表示,*用的比较多

  • 参数模式

    • 写法1:直接按照方法的参数列表写具体类型,上例的方法中参数列表(int i,String s),就可以直接在表达式中写(int,String)
    • 写法2:使用通配符:
      • “()”表示方法没有任何参数;
      • “(..)”表示匹配接受任意个参数的方法
      • “(..,java.lang.String)”表示匹配接受java.lang.String类型的参数结束,且其前边可以接受有任意个参数的方法
      • “(java.lang.String,..)” 表示匹配接受java.lang.String类型的参数开始,且其后边可以接受任意个参数的方法
      • “(*,java.lang.String)” 表示匹配接受java.lang.String类型的参数结束,且其前边接受有一个任意类型参数的方法;
  • 异常模式(可省略)

    throws Exception1,Exception2.。。。

  • 传入参数(可省略)

    ​ and args(arg-name),一般用于AfterAdvice和Around通知

四、前期准备

  1. 创建项目,导入相关jar包,参考Spring——IOC,此外还需导入aop和aspectj的jar包
  2. 创建applicationContext.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:context="http://www.springframework.org/schema/context"         xmlns:aop="http://www.springframework.org/schema/aop"