AOP相关术语:

Joinpoint (连接点):所谓连接点是指那些被拦截到的点,在spring中,这些点指的是方法,因为spring 只支持方法类型的连接点。

Pointcut(切入点):所谓切入点是指我们要对那些Joinpoint进行拦截的定义。

Adevice(通知/增强):所谓通知是指拦截到Joinpoint之后要做的事,分为前置通知,后置通知,异常通知,最终通知,环绕通知(切面要完成的功能)

Introduction(引介):引介是一种特殊的通知在不修改类代码的前提下,Introduction可以在运行期为类动态的添加一些方法或Field

Target(目标对象):代理的目标对象

Weaving(织入):是指把增强应用到目标对象来创建新的代理对象的过程。spring 采用动态代理织入,而AspectJ采用编译器织入和类装载期织入

Proxy(代理):一个类被AOP织入增强后,就产生一个结果代理类

Aspect(切面):是切入点和通知(引介)的结合

通知类型:

  • 前置通知:在目标方法执行前执行
  • 后置通知:在目标方法执行后执行
  • 环绕通知:在目标方法执行前和执行后通知
  • 异常抛出通知:在目标方法出现异常时执行
  • 最终通知:无论目标方法是否出现异常,最终通知都会执行

引入AOP约束:

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

第一种方式我们可以在Xml文件中进行配置:

编写目标对象:

public interface PersonDao {
public String savePerson();
}
 public class PersonDaoImpl implements PersonDao {
@Override
public String savePerson() {
System.out.println("save person");
return "return SavePerson";
}
}

编写切面类 进行事务管理:

 package com.person;

 import javax.persistence.criteria.Join;

 import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint; public class Transaction {
/**
* 前置通知
* JoinPoint
* 连接点,代表一个方法,客户端调用哪个方法那个方法就是连接点
* 通过该参数,可以获取到连接点的一些信息
* @param joinPoint
*/
public void beginTransaction(JoinPoint joinPoint){
//获取目标类
System.out.println("targetClass " + joinPoint.getTarget());
//获取连接点的参数
System.out.println("args " + joinPoint.getArgs());
//获取连接点的名称
System.out.println("methodName " + joinPoint.getSignature().getName());
System.out.println("开启事务");
}
/**
* 后置通知 方法遇到异常 不执行
* JoinPoint 连接点
* Object val 接受目标方法的返回值 与配置文件中参函数名一致
* @param joinPoint
*/
public void commit(JoinPoint joinPoint,Object val){
System.out.println(val);
System.out.println("事务提交"); }
/**
* 最终通知 无论是否发生异常都会执行
* @param joinPoint
*/
public void finalyMethod(JoinPoint joinPoint){
System.out.println("finally method");
}
/**
* 异常通知
* @param joinPoint 连接点
* @param ex 接收异常 在文件中配置 参数名一致
*/
public void throwingMethod(JoinPoint joinPoint,Throwable ex) {
System.out.println(ex.getMessage());
}
/**
* 环绕通知 在方法前后执行 能够控制方法是否执行
* 其主要在于,
* 如果使用around 来作为切入面,连接点的方法就嵌套在around中来执行,
* 如果around中不获取连接点来执行方法,那么原本的方法不会执行
*
* 如果在around执行时同样使用了aftereturning来拦截return就必须,
* 在around中执行方法的哪一行就行return的获取,再由around再次进行return,
* 否则afterreturning是拦截不到return的,因为return在around已经断掉了
*
* 注意在around 中使用的是 ProceedingJoinPoint
* @param joinPoint
* @throws Throwable
*/
public Object aroundMethod(ProceedingJoinPoint joinPoint) throws Throwable{
System.out.println("aaaaaa");
Object val = joinPoint.proceed();//执行目标方法
System.out.println("bbbbbb");
return val;
}
//public void aroundMethod(ProceedingJoinPoint joinPoint) throws Throwable{
// System.out.println("aaaaaa");
//// Object val = joinPoint.proceed();//执行目标方法
// System.out.println("bbbbbb");
//// return val;
//}
}

修改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:aop="http://www.springframework.org/schema/aop" xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd">
<bean id="personDao" class="com.person.PersonDaoImpl"></bean>
<bean id="transaction" class="com.person.Transaction"></bean>
<aop:config>
<aop:pointcut
expression="execution(* com.person.PersonDaoImpl.*(..))"
id="perform"/>
<!-- 切面 -->
<aop:aspect ref="transaction">
<!-- 前置通知 -->
<aop:before method="beginTransaction" pointcut-ref="perform"/>
<!-- 后置通知
1、在目标方法执行之后执行 2、能够获取到目标方法的返回值 returning="val" val:和后置通知方法的接收参数名一样 3、如果目标方法遇到异常,则后置通知将不执行 -->
<aop:after-returning method="commit" pointcut-ref="perform" returning="val"/>
<!-- 最终通知 不管目标方法是否遇到异常,最终通知都将执行 -->
<aop:after method="finalyMethod" pointcut-ref="perform"/>
<!-- 异常通知 获取目标方法抛出的异常 throwing="ex"和方法中的第二个参数的名称一致 -->
<aop:after-throwing method="throwingMethod" pointcut-ref="perform" throwing="ex"/>
<!-- 环绕通知 能够控制目标方法的执行 -->
<!-- <aop:around method="aroundMethod" pointcut-ref="perform"/> -->
</aop:aspect>
</aop:config> </beans>

测试代码:

 import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext; public class PersonTest { public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("person.xml");
PersonDao personDao = (PersonDao) context.getBean("personDao"); personDao.savePerson();
}
}

输出结果如下:

targetClass   com.person.PersonDaoImpl@713055ba
args  [Ljava.lang.Object;@20a07db0
methodName  savePerson
开启事务
save person
return SavePerson
事务提交
finally method

第二种方式我们可以利用注解来配置

编写目标对象:

 public class Book {

     public String add() {
System.out.println("add....books.....");
return "return Save";
}
public void query() {
System.out.println("query.........");
}
public void delete () {
System.out.println("delete....books....."); }
}

编写切面类:

 import org.aspectj.lang.JoinPoint;
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;
//声明切入面
@Aspect
public class BookAspect { //在方法上面使用注解完成增强配置
@Before(value="execution(* cn.aop.Book.*(..))")
public void before(JoinPoint joinPoint) {
//获取目标类
System.out.println("target :" + joinPoint.getTarget());
//获取连接点的参数
System.out.println("args :" + joinPoint.getArgs());
//获取链接点的名称
System.out.println("methodName :" + joinPoint.getSignature().getName());
System.out.println("before..............");
} @After(value="execution(* cn.aop.Book.*(..))" )
public void after() {
System.out.println("after..............");
}
// @AfterReturning(pointcut="pointcut1",returning="val")
// @AfterReturning(value="execution(* cn.aop.Book.*(..))",returning="val")
public void afterReturning(Object val){
System.out.println(val);
System.out.println("afterReturning...."); }
@AfterThrowing(value = "execution(* cn.aop.Book.*(..))")
public void afterThrowing(){
System.out.println("afterThrowing....."); }
@Around(value="execution(* cn.aop.Book.*(..))")
public Object around(ProceedingJoinPoint joinPoint) throws Throwable{
System.out.println("aaaaaa");
Object val = joinPoint.proceed();
System.out.println("bbbbbb");
return val;
} }

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:aop="http://www.springframework.org/schema/aop" xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd"> <!-- 开启aop操作 -->
<aop:aspectj-autoproxy></aop:aspectj-autoproxy>
<!-- 1 配置对象 -->
<bean id="book" class="cn.aop.Book"></bean>
<bean id="BookAspect" class="cn.aop.BookAspect"></bean> <!-- <aop:config>
<aop:pointcut expression="execution(* cn.aop.Book.*(..))" id="pointcut1"/>
</aop:config> -->
</beans>

编写测试类:

 import javax.sound.midi.Soundbank;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext; public class TestBook { public void testDemo(){
ApplicationContext context =
new ClassPathXmlApplicationContext("book.xml");
Book book = (Book) context.getBean("book");
book.add();
System.out.print("\n");
book.delete();
// System.out.println("\n");
// System.out.println(book.query());
}
public static void main(String[] args) {
TestBook test = new TestBook();
test.testDemo();
}
}

测试结果:

aaaaaa
target :cn.aop.Book@61fc0ce6
args :[Ljava.lang.Object;@55a19181
methodName :add
before..............
add....books.....
bbbbbb
after.............. aaaaaa
target :cn.aop.Book@61fc0ce6
args :[Ljava.lang.Object;@1b6cdb87
methodName :delete
before..............
delete....books.....
bbbbbb
after..............

Spring 之AOP 面向切面编程的更多相关文章

  1. Spring:AOP面向切面编程

    AOP主要实现的目的是针对业务处理过程中的切面进行提取,它所面对的是处理过程中的某个步骤或阶段,以获得逻辑过程中各部分之间低耦合性的隔离效果. AOP是软件开发思想阶段性的产物,我们比较熟悉面向过程O ...

  2. Spring 08: AOP面向切面编程 + 手写AOP框架

    核心解读 AOP:Aspect Oriented Programming,面向切面编程 核心1:将公共的,通用的,重复的代码单独开发,在需要时反织回去 核心2:面向接口编程,即设置接口类型的变量,传入 ...

  3. Spring框架 AOP面向切面编程(转)

    一.前言 在以前的项目中,很少去关注spring aop的具体实现与理论,只是简单了解了一下什么是aop具体怎么用,看到了一篇博文写得还不错,就转载来学习一下,博文地址:http://www.cnbl ...

  4. Spring的AOP面向切面编程

    什么是AOP? 1.AOP概念介绍 所谓AOP,即Aspect orientied program,就是面向方面(切面)的编程. 功能: 让关注点代码与业务代码分离! 关注点: 重复代码就叫做关注点: ...

  5. spring:AOP面向切面编程02

    参考: https://blog.csdn.net/jeffleo/article/details/54136904 一.AOP的核心概念AOP(Aspect Oriented Programming ...

  6. Spring注解 - AOP 面向切面编程

    基本概念: AOP:Aspect Oriented Programming,即面向切面编程 指在程序运行期间动态的将某段代码切入到指定方法指定位置进行运行的编程方式 前置通知(@Before):在目标 ...

  7. Spring框架——AOP面向切面编程

    简介 AOP练习 使用动态代理解决问题 Spring AOP 用AspectJ注解声明切面 前置后置通知 利用方法签名编写AspectJ切入点表达式 指定切面的优先级 基于XML的配置声明切面 Spr ...

  8. Spring之AOP(面向切面编程)_入门Demo

    AOP是OOP的延续,是Aspect Oriented Programming的缩写,意思是面向切面编程.AOP实际是GoF设计模式的延续,设计模式孜孜不倦追求的是调用者和被调用者之间的解耦,AOP可 ...

  9. 【spring源码学习】spring的AOP面向切面编程的实现解析

    一:Advice(通知)(1)定义在连接点做什么,为切面增强提供织入接口.在spring aop中主要描述围绕方法调用而注入的切面行为.(2)spring定义了几个时刻织入增强行为的接口  => ...

  10. 详解Spring框架AOP(面向切面编程)

    最近在学习AOP,之前一直很不明白,什么是AOP?为什么要使用AOP,它有什么作用?学完之后有一点小小的感触和自己的理解,所以在这里呢就跟大家一起分享一下 AOP(Aspect-Oriented Pr ...

随机推荐

  1. 无插件纯Web 3D机房,HTML5+WebGL倾力打造

    前言 最近项目开发任务告一段落,刚好有时间整理这大半年的一些成果.使用html5时间还不久,对js的认识还不够深入.没办法,以前一直搞java,对js的一些语言特性和概念一时还转换不过来. 上一篇大数 ...

  2. vue+VeeValidate 校验范围(部分校验,全部校验)

    搜索很久,没有发现有关于vue+VeeValidate部分校验的.自己写一个. 主要是两个场景: 1. 校验范围内,所有的字段. 2. 校验全局所有字段.主要方法: 1.validate(fields ...

  3. group 和 gshadow

    group组文件 位置:/etc/group 作用:存放用户的分组信息 使用 /etc/group 命令查看时,得到的数据如下: 分析上图,可以得到以下结果 第1个字段:组名 默认组名与用户名名称一样 ...

  4. MySql-count(*)与count(id)与count(字段)之间的执行结果和性能分析

    在mysql数据库中,当我们需要统计数据的时候,一定会用到count()这个方法,那么count(值)里面的这个值,到底应该怎么选择呢!常见有3种选择,(*,数字,列名),分别列出它们的执行结果和性能 ...

  5. Buffer.from()

    Buffer.from(array) array {Array} 使用一个8位字节的数组分配一个新的 Buffer. const buf = Buffer.from([0x62, 0x75, 0x66 ...

  6. mac 解决mysql启动不了

    mac升级了mysql,没有替换原来的链接的情况下, 启动mysql restart 会失败 解决方法,找到mysql真正的安装目录 mysql.server start

  7. CSS+DIV命名

    原地址:http://www.cnblogs.com/hylaz/archive/2012/10/27/2742743.html#2521377 页头:header 登录条:loginBar 标志:l ...

  8. python 库文件版本收集及安装

    版本收集:pip freeze > require.txt版本安装:pip install -r require.txt

  9. 模板 求GCD&LCM

    求最大公倍数 int GCD(int a,int b) { ) return b; else return GCD(b,a%b); } 求最小公倍数 int LCM(int a,int b) { re ...

  10. 精帖转载(关于stock problem)

    Note: this is a repost(重新投寄) of my original post here with updated solutions(解决方案) for this problem ...