spring aop介绍和示例
参考:《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介绍和示例的更多相关文章
- Spring AOP介绍与使用
Spring AOP介绍与使用 AOP:Aspect Oriented Programming 面向切面编程 OOP:Object Oriented Programming 面向对象编程 面向切面 ...
- Spring AOP 介绍与基于接口的实现
热烈推荐:超多IT资源,尽在798资源网 声明:转载文章,为防止丢失所以做此备份. 本文来自公众号:程序之心 原文地址:https://mp.weixin.qq.com/s/vo94gVyTss0LY ...
- Spring AOP介绍
1.介绍 AOP(面向切面编程)对OOP(面向对象编程)是一种补充,它提供了另一种程序结构的思路.OOP的模块单元是class,而AOP的模块单元是aspect.Spring中一个关键的组件是AOP框 ...
- Spring AOP介绍及源码分析
转自:http://www.uml.org.cn/j2ee/201301102.asp 软件开发经历了从汇编语言到高级语言和从过程化编程到面向对象编程:前者是为了提高开发效率,而后者则使用了归纳法,把 ...
- Spring AOP的简单示例
配置文件 <?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://w ...
- Spring aop 简单示例
简单的记录一下spring aop的一个示例 基于两种配置方式: 基于xml配置 基于注解配置 这个例子是模拟对数据库的更改操作添加事物 其实并没有添加,只是简单的输出了一下记录 首先看下整个例子的目 ...
- 《Spring 5官方文档》 Spring AOP的经典用法
原文链接 在本附录中,我们会讨论一些初级的Spring AOP接口,以及在Spring 1.2应用中所使用的AOP支持. 对于新的应用,我们推荐使用 Spring AOP 2.0来支持,在AOP章节有 ...
- Spring AOP 和 动态代理技术
AOP 是什么东西 首先来说 AOP 并不是 Spring 框架的核心技术之一,AOP 全称 Aspect Orient Programming,即面向切面的编程.其要解决的问题就是在不改变源代码的情 ...
- Spring Boot实践——Spring AOP实现之动态代理
Spring AOP 介绍 AOP的介绍可以查看 Spring Boot实践——AOP实现 与AspectJ的静态代理不同,Spring AOP使用的动态代理,所谓的动态代理就是说AOP框架不会去修改 ...
随机推荐
- Spring源码剖析2:Spring IOC容器的加载过程
spring ioc 容器的加载流程 1.目标:熟练使用spring,并分析其源码,了解其中的思想.这篇主要介绍spring ioc 容器的加载 2.前提条件:会使用debug 3.源码分析方法:In ...
- seq2seq通俗理解----编码器和解码器(TensorFlow实现)
1. 什么是seq2seq 在⾃然语⾔处理的很多应⽤中,输⼊和输出都可以是不定⻓序列.以机器翻译为例,输⼊可以是⼀段不定⻓的英语⽂本序列,输出可以是⼀段不定⻓的法语⽂本序列,例如: 英语输⼊:&quo ...
- C#数据结构_树
树的定义是递归的,用树来定义树.因此,树(以及二叉 树)的许多算法都使用了递归. 结点(Node):表示树中的数据元素. 结点的度(Degree of Node):结点所拥有的子树的个数. 树的度(D ...
- Codeforces 1009G
题意略. 思路: 首先是贪心, 我们从前往后依次从小到大考虑放哪个字符, 重点是判断放了这个字符后, 对于剩下的后缀是否存在合法解. 考虑每个位置的允许放的字符集合只有2 ^ 6种, 我们预处理一个后 ...
- 变量声明关键字var ,let,const
今天带大家了解的是比较有趣的几个变量声明关键字var,let,const. 我们在最初接触JS的时候,变量是我们重要的一个组成部分,在使用时规定必须要先进行声明,否则网页将会报错: console.l ...
- C++ socket bind()函数报错 不存在从 "std::_Binder<std::_Unforced, SOCKET &, sockaddr *&, size_t &>" 到 "int" 的适当转换函数
昨天还可以正常运行的程序,怎么今天改了程序的结构就报错了呢?我明明没有改动函数内部啊!!! 内心无数只“草泥马”在奔腾,这可咋办呢?于是乎,小寅开始求助于亲爱的度娘...... 由于小寅知识水平有限, ...
- 一文带您了解 Elasticsearch 中,如何进行索引管理(图文教程)
欢迎关注笔者的公众号: 小哈学Java, 每日推送 Java 领域干货文章,关注即免费无套路附送 100G 海量学习.面试资源哟!! 个人网站: https://www.exception.site/ ...
- 探索Asp net core3中的 项目文件、Program.cs和通用host(译)
引言 原文地址 在这篇博客中我将探索一些关于Asp.net core 3.0应用的基础功能--.csproj 项目文件和Program源文件.我将会描述他们从asp.net core 2.X在默认模版 ...
- spring boot环境配置
Eclipse+Maven创建webapp项目<一> 1.开启eclipse,右键new——>other,如下图找到maven project 2.选择maven project,显 ...
- ParquetDecodingException: Can not read value at 0 in block -1 in file hdfs:...
: jdbc:hive2://master01.hadoop.dtmobile.cn:1> select * from cell_random_grid_tmp2 limit 1; INFO : ...