1、什么是AOP

AOP = Aspect Oriental Programing,即面向切面编程。什么概念,我们看如下的图片:

三个方法中,重复使用了代码A和代码B,典型的场景比如“开启事务,数据处理,提交事务”。这些重复的代码大多是所谓的权限管理、日志登陆、事务管理等必需却又污染着业务逻辑代码的内容,我们自然希望将它们提取出来,还业务逻辑一个清新的世界。

你知道Servlet过滤器,可我们目前对象的粒度已经不是整个方法了,而是更加细化到了方法中的代码片段。你当然可以曲线救国地使用匿名内部类来抽取重复代码,但是它并不怎么优雅,而AOP,就可以通过横向切割的方式来抽取代码,达到我们的目的。

2、Spring AOP

首先来看一下Spring AOP中一些核心组件的概念:
  • 切面:封装通用业务逻辑的组件,即我们想要插入的代码内容
  • 切入点:指定哪些Bean组件的哪些方法使用切面组件
  • 通知:用于指定具体作用的位置,是方法之前或之后等等
    • 前置通知(before) - 在目标方法被调用之前调用通知功能
    • 后置通知(after) - 在目标方法完成之后调用通知(不论程序是否出现异常),此时不会关心方法的输出是什么
    • 返回通知(after-returning) - 在目标方法成功执行之后调用通知
    • 异常通知(after-throwing) - 在目标方法抛出异常后调用通知
    • 环绕通知(around) - 通知包裹了被通知的方法,在被通知的方法调用之前和调用之后执行自定义的行为

那么在Spring中使用AOP就意味着你需要:
  • 目标程序,某个需要被插入通用代码片段的方法
  • 切面程序,即通用代码,用来插入方法的那些代码片段(无返回类型,参数类型与通知类型有关)
  • 配置文件,用来指定切入点和通知

3、Demo示例和说明

下面就来看一个简单的Spring AOP的Demo

3.1相关配置环境

<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>4.3.16.RELEASE</version>
</dependency> <dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aspects</artifactId>
<version>4.3.16.RELEASE</version>
</dependency>
11
 
1
<dependency>
2
    <groupId>org.springframework</groupId>
3
    <artifactId>spring-context</artifactId>
4
    <version>4.3.16.RELEASE</version>
5
</dependency>
6

7
<dependency>
8
    <groupId>org.springframework</groupId>
9
    <artifactId>spring-aspects</artifactId>
10
    <version>4.3.16.RELEASE</version>
11
</dependency>

3.2 准备一个目标程序

编写某个目标程序,并注册为Spring的Bean组件
public class Target {

    public void print(String param) {
System.out.println("I'm a target function and my param is [" + param + "]" );
} }
7
 
1
public class Target {
2

3
    public void print(String param) {
4
        System.out.println("I'm a target function and my param is [" + param + "]" );
5
    }
6

7
}

3.3 编写切面程序

编写切面程序,并注册为Spring的Bean组件
  • 切面程序必须无返回值,即void
  • org.aspectj.lang.JoinPoint 封装了切面方法的参数和对象等,可通过它获取相关内容
  • 切面程序的参数除JoinPoint外,还与通知类型有关,如后置通知则可以获取目标程序返回值(需要配置,此处不展开)
public class Section {

    public void writeLog(JoinPoint point) {
System.out.println("write logs start"); System.out.println("获取目标函数的参数: " + Arrays.toString(point.getArgs()));
System.out.println("获取目标函数的反射对象: " + point.getSignature());
System.out.println("获取目标函数的所在对象: " + point.getTarget()); System.out.println("write logs end");
} }
13
 
1
public class Section {
2

3
    public void writeLog(JoinPoint point) {
4
        System.out.println("write logs start");
5

6
        System.out.println("获取目标函数的参数: " + Arrays.toString(point.getArgs()));
7
        System.out.println("获取目标函数的反射对象: " + point.getSignature());
8
        System.out.println("获取目标函数的所在对象: " + point.getTarget());
9

10
        System.out.println("write logs end");
11
    }
12

13
}

3.4 编写AOP配置文件

配置文件applicationContext(注册Bean和AOP配置)
<bean id="target" class="dulk.learn.aop.Target"/>
<bean id="section" class="dulk.learn.aop.Section"/> <!-- AOP配置的根标签,所有AOP配置都在其内部 -->
<aop:config>
<!-- 配置AOP的切入点,expression为切入点表达式 -->
<aop:pointcut id="targetPointCut" expression="execution(* dulk.learn.aop.Target.print(*))" />
<!-- 配置切面,ref 切面对象 -->
<aop:aspect ref="section">
<!-- 配置通知为前置,method为方法,pointcut-ref作用在哪些切入点 -->
<aop:before method="writeLog" pointcut-ref="targetPointCut"/>
</aop:aspect> </aop:config>
14
 
1
<bean id="target" class="dulk.learn.aop.Target"/>
2
<bean id="section" class="dulk.learn.aop.Section"/>
3

4
<!-- AOP配置的根标签,所有AOP配置都在其内部 -->
5
<aop:config>
6
    <!-- 配置AOP的切入点,expression为切入点表达式 -->
7
    <aop:pointcut id="targetPointCut" expression="execution(* dulk.learn.aop.Target.print(*))" />
8
    <!-- 配置切面,ref 切面对象 -->
9
    <aop:aspect ref="section">
10
        <!-- 配置通知为前置,method为方法,pointcut-ref作用在哪些切入点 -->
11
        <aop:before method="writeLog" pointcut-ref="targetPointCut"/>
12
    </aop:aspect>
13

14
</aop:config>

3.4.1 切入表达式


如上说明,则该demo中的 execution(* dulk.learn.aop.Target.print(*)) 表示 “Target类中的print方法(不论参数,即包括其重载)”

3.4.2 切面配置说明

<!-- 配置切面,ref 切面对象的beanId -->
<aop:aspect ref="section">
<!-- before表通知为前置,method为插入的方法,pointcut-ref作用在哪些切入点(aop:pointcut id) -->
<aop:before method="writeLog" pointcut-ref="targetPointCut"/>
</aop:aspect>
 
1
<!-- 配置切面,ref 切面对象的beanId -->
2
<aop:aspect ref="section">
3
    <!-- before表通知为前置,method为插入的方法,pointcut-ref作用在哪些切入点(aop:pointcut id) -->
4
    <aop:before method="writeLog" pointcut-ref="targetPointCut"/>
5
</aop:aspect>

3.5 测试程序和结果

public class AOPTest {

    @Test
public void testAOP(){
ApplicationContext context = new ClassPathXmlApplicationContext("/applicationContext.xml");
Target target = (Target) context.getBean("target");
target.print("balabala");
} }
10
 
1
public class AOPTest {
2

3
    @Test
4
    public void testAOP(){
5
        ApplicationContext context = new ClassPathXmlApplicationContext("/applicationContext.xml");
6
        Target target = (Target) context.getBean("target");
7
        target.print("balabala");
8
    }
9

10
} 

 

4、参考链接

[08] AOP基本概念和使用的更多相关文章

  1. Spring AOP基本概念

    Spring AOP基本概念 目录 Spring AOP定义 AOP基本术语 通知类型 AOP定义 AOP基本术语 切面( Aspect ):一个能横切多个对象的模块化的关注点.对Spring AOP ...

  2. Spring入门篇——AOP基本概念

    1.什么是AOP及实现方式 什么是AOP AOP:Aspect Oriented Programming的缩写,意为:面向切面编程,通过预编译方式和运行期动态代理实现程序功能的统一维护的一种技术 主要 ...

  3. Spring入门篇——第5章 Spring AOP基本概念

    第5章 Spring AOP基本概念 本章介绍Spring中AOP的基本概念和应用. 5-1 AOP基本概念及特点 5-2 配置切面aspect ref:引用另外一个Bean 5-3 配置切入点Poi ...

  4. Spring学习总结(1)——Spring AOP的概念理解

    1.我所知道的aop 初看aop,上来就是一大堆术语,而且还有个拉风的名字,面向切面编程,都说是OOP的一种有益补充等等.一下子让你不知所措,心想着:怪不得 很多人都和我说aop多难多难 .当我看进去 ...

  5. Spring Aop重要概念介绍及应用实例结合分析

    转自:http://bbs.csdn.net/topics/390811099 此前对于AOP的使用仅限于声明式事务,除此之外在实际开发中也没有遇到过与之相关的问题.最近项目中遇到了以下几点需求,仔细 ...

  6. Spring AOP入门——概念和注意事项

    AOP什么? AOP在功能方面,它是之前和之后运行一些业务逻辑,一些操作(比方记录日志.或者是推断是否有权限等),这些操作的加入.全然不耦合于原来的业务逻辑.从而对原有业务逻辑全然是透明. 也就是说. ...

  7. Spring学习(18)--- AOP基本概念及特点

    AOP:Aspect Oriented Programing的缩写,意为:面向切面编程,通过预编译方式和运行期动态代理实现程序程序功能的统一维护的一种技术 主要的功能是:日志记录,性能统计,安全控制, ...

  8. Spring Core Programming(Spring核心编程) - AOP Concepts(AOP基本概念)

    1. What is aspect-oriented programming?(什么是面向切面编程?) Aspects help to modularize cross-cutting concern ...

  9. Spring课程 Spring入门篇 5-1 aop基本概念及特点

    概念: 1 什么是aop及实现方式 2 aop的基本概念 3 spring中的aop 1 什么是aop及实现方式 1.1 aop,面向切面编程,比如:唐僧取经需要经过81难,多一难少一难都不行.孙悟空 ...

随机推荐

  1. docker第一章:docker核心概念及centos6下安装

    Docker三大核心概念 镜像 容器 仓库 镜像 docker镜像类似于虚拟机镜像,可以将它理解为一个面向Docker引擎的只读模板,包含了文件系统. 容器 1.容器是从镜像创建的应用运行实例,容器和 ...

  2. 微信小程序/网站 上传图片到腾讯云COS

    COS简介: 腾讯云提供的一种对象存储服务,供开发者存储海量文件的分布式存储服务.可以将自己开发的应用的存储部分全部接入COS的存储桶中,有效减少应用服务器的带宽,请求等.个人也可以通过腾讯云账号免费 ...

  3. 无法给MySQL root用户修改密码的解决方法

    本人编译安装完MySQL数据库,想给root用户修改密码,结果无法修改,并且报错,报错大概信息如下: mysqladmin: connect to server at 'localhost' fail ...

  4. Visualforce简介

    Visualforce Visualforce是一个和Apex语言相匹配的开发框架.开发者可以使用Visualforce和Apex建立自定义网络应用程序. Visualforce的基本功能类似于前端框 ...

  5. 【BI学习笔记】适合集成到项目里的BI:Wyn Enterprise

    近日,我收到葡萄城的邮件,讲葡萄城开始进军BI领域,发布了一套BI和报表工具,叫Wyn Enterprise. 之前了解过PowerBI等面向终端用户的BI工具,我发现BI工具与Wyn Enterpr ...

  6. 安卓开发之Room实体定义数据

    使用Room实体定义数据 在Room库中,entities(实体)代表着相关字段集.每一个entity(实体)代表着相关联数据库中的一个表.entity 类必须通过Database 类中的entiti ...

  7. springboot 升级到2.0后 context-path 配置 不起作用,不生效 不管用 皆是因为版本改动导致的在这里记录一下

    不知不觉,新的项目已经将springboot升级为2.0版本了.刚开始没有配置server.contextpath,默认的“/”,然后今天放到自己的服务器上,所以就要规范名称.  结果,失败了,无论我 ...

  8. 13.1、多进程:进程锁Lock、信号量、事件

    进程锁: 为什么要有进程锁:假如现在有一台打印机,qq要使用打印机,word文档也要使用打印机,如果没有使用进程锁,可能会导致一些问题,比如QQ的任务打印到一半,Word插进来,于是打印出来的结果是各 ...

  9. CSS中各种长度单位总结

    在前端开发工作过程中曾碰到这样一问题: <style type="text/css"> .parent{ width:400px; height:300px; bord ...

  10. fedora 使用 vnc 远程 fedora 28 主机

    问题重述: 最近环境中需要使用 fedora 28 来进行远程桌面,于是就重新配置了一下vnc 在这里面做一下记录. 过程: yum 安装: 工作机上安装 vncviewer 远程主机上安装: vnc ...