参考:《Spring in Action》

一、AOP介绍

AOP是Aspect Oriented Programming的缩写,意思是面向切面编程。

应用中有一些功能使用非常普遍,比如事务、安全、缓存,它们和业务没有直接关系,但是往往要嵌入到应用的业务逻辑当中,这些功能被称为横切关注点。而将这些横切关注点与业务逻辑相分离、减少之间的耦合性,就是面向切面编程(AOP)所要做的工作。

下面是AOP的常用术语:

1、切面(Aspect)

相似的横切关注点可以被集中模块化为一个特殊的类,这个类被称为切面。

例如应用里dao层的一些方法里分布着很多事务代码,现在将这些代码抽取出来,集中到一个事务处理类中(切面),dao层之后可以只关注自己的核心功能,而将事务部分移交给事务处理类来做。

切面是通知和切点结合,它们共同定义了切面的全部内容:它做什么、在何时做、在何处做。

3、通知(Advice)

切面要做的工作被称为通知,不同类型的通知又决定了切面的执行时机。

spring切面可以应用5种类型的通知:

before:在方法被调用之前调用通知
after:在方法完成之后调用通知,无论方法执行是否成功
after-returning:在方法成功执行之后调用通知
after-throwing:在方法抛出异常后调用通知
around:通知包裹了被通知的方法,在被通知的方法调用之前和调用之后执行自定义的行为

4、连接点(Joinpoint)

连接点是在应用执行过程中能够插入通知的一个点,这个点可以是调用方法时、抛出异常时、甚至修改一个字段时。

5、切点(Poincut)

切点的定义会匹配通知要织入的一个或多个连接点,如果通知定义了切面"做什么"和"在何时做",切点就定义了切面"在何处做"。切点的内容可以是类和方法的名称,也可以是一段正则表达式,有的AOP框架还支持运行时创建的动态切点。

6、织入(Weaving)

织入是通知在指定的连接点被插入到应用中(目标类)的过程,这个连接点就叫做切点,而被织入的某类通知就叫做切面。

在目标类的生命周期里有多个时机可以进行织入:

编译期:通知在目标类编译时被织入,这种方式需要特殊的编译器,AspectJ的织入编译器就是用这种方式
类加载期:通知在目标类加载到JVM时被织入,这种方式需要特殊的类加载器,AspectJ5的LTW支持这种方式
运行期:通知在应用运行的某个时刻被织入,一般情况在织入时AOP容器会为目标对象动态地创建一个代理对象,spring aop就是用这种方式

二、spring对AOP的支持

1、目前主流AOP框架

AspectJ
JBoss AOP
Spring AOP

Spring AOP包含了AspectJ的一些功能,能满足许多应用的切面需求,不过和AspectJ相比功能较弱,有许多类型的切点不支持。

2、spring提供的AOP支持

基于代理的经典AOP
纯POJO切面
@AspectJ注解驱动的切面
注入式AspectJ切面

前三种属于Spring AOP,因为是基于代理的,所以对AOP的支持只有方法拦截,如果需要构造器拦截和属性拦截,就需要用第四种AspectJ

第一种经典AOP已经不常用了,实际情况中我们使用最多的是xml风格的纯POJO切面和注解风格的@AspectJ切面。

之后书本里有更详细的说明,这里就不写了,举两个栗子。

在之前配置hibernate访问mysql这篇里所附代码的基础上进行测试

三、xml风格的纯POJO切面

1、添加jar包引用,修改pom.xml文件,加入:

<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
<version>${spring.version}</version>
</dependency> <!-- aop -->
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjrt</artifactId>
<version>1.7.4</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.7.4</version>
</dependency>
<dependency>
<groupId>cglib</groupId>
<artifactId>cglib</artifactId>
<version>3.1</version>
</dependency>

2、在"src/main/java"代码文件夹的"org.xs.demo1"的包下新建"aopAdvice.java"通知类,内容为:

package org.xs.demo1;

import org.aspectj.lang.ProceedingJoinPoint;

public class aopAdvice {

    public void doBefore() {
System.out.println("aop——before");
} public void doAfter() {
System.out.println("aop——after");
} public void doAfterReturning() {
System.out.println("aop——after-returning");
} public void doAfterThrowing() {
System.out.println("aop——after-throwing");
} //joinpoint参数是被通知的方法
//如果被通知的方法有返回值,在环绕方法里面也需要返回
public Object doAround(ProceedingJoinPoint joinpoint) {
Object result = null;
try {
System.out.println("aop——around-before"); //调用被通知的方法
result = joinpoint.proceed(); System.out.println("aop——around-after");
} catch (Throwable e) {
System.out.println("aop——gg");
}
return result;
}
}

3、在"src/main/resources"代码文件夹中新建文件"spring-context-aop.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"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.2.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-3.2.xsd"> <description>AOP Configuration</description> <!-- 要织入的通知(切面) -->
<bean id="aopAdvice" class="org.xs.demo1.aopAdvice"></bean> <!-- AOP配置 -->
<aop:config>
<!-- 定义切面 -->
<aop:aspect ref="aopAdvice">
<!-- 定义切点 -->
<aop:pointcut id="performance" expression="execution(* org.xs.demo1.testDao.getList(..))" />
<!-- 定义通知 -->
<aop:before pointcut-ref="performance" method="doBefore" />
<aop:after pointcut-ref="performance" method="doAfter" />
<aop:after-returning pointcut-ref="performance" method="doAfterReturning" />
<aop:after-throwing pointcut-ref="performance" method="doAfterThrowing" />
<aop:around pointcut-ref="performance" method="doAround" />
</aop:aspect>
</aop:config>
</beans>

4、运行测试(访问localhost:8080/demo1/hello/mysql)

在Console窗口会输出信息

四、注解风格的@AspectJ切面

1、在"src/main/java"代码文件夹的"org.xs.demo1"的包下新建"aopAdvice2.java"通知类,内容为:

package org.xs.demo1;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut; @Aspect
public class aopAdvice2 { @Pointcut("execution(* org.xs.demo1.testDao.getList(..))")
public void performance() { } @Before("performance()")
public void doBefore() {
System.out.println("aop——before");
} @After("performance()")
public void doAfter() {
System.out.println("aop——after");
} @AfterReturning("performance()")
public void doAfterReturning() {
System.out.println("aop——after-returning");
} @AfterThrowing("performance()")
public void doAfterThrowing() {
System.out.println("aop——after-throwing");
} //joinpoint参数是被通知的方法
//如果被通知的方法有返回值,在环绕方法里面也需要返回
@Around("performance()")
public Object doAround(ProceedingJoinPoint joinpoint) {
Object result = null;
try {
System.out.println("aop——around-before"); //调用被通知的方法
result = joinpoint.proceed(); System.out.println("aop——around-after");
} catch (Throwable e) {
System.out.println("aop——gg");
}
return result;
}
}

2、修改"spring-context-aop.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"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.2.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-3.2.xsd"> <description>AOP Configuration</description> <!-- 要织入的通知(切面) -->
<!-- <bean id="aopAdvice" class="org.xs.demo1.aopAdvice"></bean> --> <!-- AOP配置 -->
<!-- <aop:config> -->
<!-- 定义切面 -->
<!-- <aop:aspect ref="aopAdvice"> -->
<!-- 定义切点 -->
<!-- <aop:pointcut id="performance" expression="execution(* org.xs.demo1.testDao.getList(..))" /> -->
<!-- 定义通知 -->
<!-- <aop:before pointcut-ref="performance" method="doBefore" />
<aop:after pointcut-ref="performance" method="doAfter" />
<aop:after-returning pointcut-ref="performance" method="doAfterReturning" />
<aop:after-throwing pointcut-ref="performance" method="doAfterThrowing" />
<aop:around pointcut-ref="performance" method="doAround" />
</aop:aspect>
</aop:config> --> <!-- 启动@AspectJ支持 -->
<aop:aspectj-autoproxy/> <!-- 指定自动搜索Bean组件,自动搜索切面类 -->
<context:component-scan base-package="org.xs.demo1" use-default-filters="false">
<context:include-filter type="annotation" expression="org.aspectj.lang.annotation.Aspect" />
</context:component-scan>
</beans>

3、运行测试

效果和之前的一样

注:如果要织入的是Controller类,需要把"spring-context-aop.xml"内的内容移动到"spring-mvc.xml"里,或者将"spring-context-aop.xml"文件名加入到DispatcherServlet里(用逗号分隔)。原因是在父上下文里的内容无法读取在子上下文里配置的Controller,只有将AOP的bean也放在子上下文里加载才行。

实例代码地址:https://github.com/ctxsdhy/cnblogs-example

spring aop介绍和示例的更多相关文章

  1. Spring AOP介绍与使用

    Spring AOP介绍与使用 AOP:Aspect Oriented Programming 面向切面编程 OOP:Object Oriented Programming 面向对象编程 ​ 面向切面 ...

  2. Spring AOP 介绍与基于接口的实现

    热烈推荐:超多IT资源,尽在798资源网 声明:转载文章,为防止丢失所以做此备份. 本文来自公众号:程序之心 原文地址:https://mp.weixin.qq.com/s/vo94gVyTss0LY ...

  3. Spring AOP介绍

    1.介绍 AOP(面向切面编程)对OOP(面向对象编程)是一种补充,它提供了另一种程序结构的思路.OOP的模块单元是class,而AOP的模块单元是aspect.Spring中一个关键的组件是AOP框 ...

  4. Spring AOP介绍及源码分析

    转自:http://www.uml.org.cn/j2ee/201301102.asp 软件开发经历了从汇编语言到高级语言和从过程化编程到面向对象编程:前者是为了提高开发效率,而后者则使用了归纳法,把 ...

  5. Spring AOP的简单示例

    配置文件 <?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://w ...

  6. Spring aop 简单示例

    简单的记录一下spring aop的一个示例 基于两种配置方式: 基于xml配置 基于注解配置 这个例子是模拟对数据库的更改操作添加事物 其实并没有添加,只是简单的输出了一下记录 首先看下整个例子的目 ...

  7. 《Spring 5官方文档》 Spring AOP的经典用法

    原文链接 在本附录中,我们会讨论一些初级的Spring AOP接口,以及在Spring 1.2应用中所使用的AOP支持. 对于新的应用,我们推荐使用 Spring AOP 2.0来支持,在AOP章节有 ...

  8. Spring AOP 和 动态代理技术

    AOP 是什么东西 首先来说 AOP 并不是 Spring 框架的核心技术之一,AOP 全称 Aspect Orient Programming,即面向切面的编程.其要解决的问题就是在不改变源代码的情 ...

  9. Spring Boot实践——Spring AOP实现之动态代理

    Spring AOP 介绍 AOP的介绍可以查看 Spring Boot实践——AOP实现 与AspectJ的静态代理不同,Spring AOP使用的动态代理,所谓的动态代理就是说AOP框架不会去修改 ...

随机推荐

  1. MySQL数据库之单表查询中关键字的执行顺序

    目录 MySQL数据库之单表查询中关键字的执行顺序 1 语法顺序 2 执行顺序 3 关键字使用语法 MySQL数据库之单表查询中关键字的执行顺序 1 语法顺序 select distinct from ...

  2. Java集合框架之Set接口浅析

    Java集合框架之Set接口浅析 一.java.util.Set接口综述: 这里只对Set接口做一简单综述,其具体实现类的分析,朋友们可关注我后续的博文 1.1Set接口简介 java.util.se ...

  3. Leetcode之回溯法专题-131. 分割回文串(Palindrome Partitioning)

    Leetcode之回溯法专题-131. 分割回文串(Palindrome Partitioning) 给定一个字符串 s,将 s 分割成一些子串,使每个子串都是回文串. 返回 s 所有可能的分割方案. ...

  4. 命令行通过入参调用jar包

    命令行通过入参调用jar包 最近因为项目需要,需要实现一个功能,即定时执行服务器上的一个脚本去对数据库的数据进行业务处理,要操作的数据库有很多种,mysql.db2.oracle.sqlserver等 ...

  5. vue+vscode+nodejs 开发环境搭建

    nodejs安装配置 1.下载 地址:https://nodejs.org/en/ 2.默认安装 安装完成后,执行npm -v 出现版本号则表示安装成功. 3.配置 在node安装目录下新建两个文件夹 ...

  6. bdtrans 一个命令行下的机器翻译工具

    现如今,机器翻译技术已经越来越成熟了,尽管从整体来看机器翻译的结果还不是特别如意,但是也足以应付一般的翻译需求了.近几年机器翻译平台层出不穷,国外比较出名的翻译平台有Google翻译.必应翻译等,国内 ...

  7. 洛谷 P1070 道路游戏 DP

    P1070 道路游戏 题意: 有一个环,环上有n个工厂,每个工厂可以生产价格为x的零钱收割机器人,每个机器人在购买后可以沿着环最多走p条边,一秒走一条,每条边不同时间上出现的金币是不同的,问如何安排购 ...

  8. LuoGu-P1239计数器-强大的贡献

    P1239 计数器 题意:就是求从1到n间,1-9一共出现的次数 这道题直接暴力是不科学的,因为N有 1e9: 然后我就看到了一个很好的从贡献思考的方法: ——>转自洛谷学神的方法: 楼下dal ...

  9. HDU 4289 Control 最小割

    Control 题意:有一个犯罪集团要贩卖大规模杀伤武器,从s城运输到t城,现在你是一个特殊部门的长官,可以在城市中布置眼线,但是布施眼线需要花钱,现在问至少要花费多少能使得你及时阻止他们的运输. 题 ...

  10. CSU 1809 Parenthesis 思维+线段树

    1809: Parenthesis Submit Page     Summary    Time Limit: 5 Sec     Memory Limit: 128 Mb     Submitte ...