摘要

本文内容为我在网上搜集Spring AOP资料的汇总、摘抄。

AOP是一种编程思想,其对不同对象进行了横向的抽象,将不同对象的、和主流程无关的公共逻辑抽象出来以方便维护。AOP的实现基础为AOP动态代理,动态代理又可以由JDK动态代理和CGLIB实现。Spring中AOP的编程模型是定义组件、定义切入点、定义增强功能。

关键词:SpringAOP

一、AOP简介

1. 什么是AOP

AOP(Aspect Oriented Programming,面向切面编程),横向抽象的一种编程思想,是对OOP(Object Oriented Programming,面向对象编程)的补充和完善。

OOP中的基本三个基本特征:封装继承多态,其对象关系的描述是纵向的,对于分散在不同对象、同一层面的代码却无能为力。比如需要在代码开头和结尾处都打印相同的日志,就没有办法描述这种业务了。

AOP则可以解决这个问题,它可以将不同代码同一层次的业务无关的公共逻辑抽象出来,再把代码逻辑织入到对应的切面点,这样就可以减少重复代码,以及方便维护了。

AOP的应用可以有权限认证、日志、事务等。

2. AOP的一些概念

概念 解释
核心关注点 业务处理的主要流程为核心关注点
横切关注点 与业务处理主要流程不相关的部分为横切关注点(特征:分散
切面(aspect) 切面为对横切关注点的抽象
连接点(joinpoint) 被拦截的点,在Spring中为拦截到的方法
切入点(pointcut) 对连接点进行拦截的定义
通知(adivce) 指拦截到连接点后,要执行的代码。可以分为:前置后置异常最终环绕
目标对象 代理的目标对象
织入(weave) 将切面应用到目标对象,产生代理对象的过程。(即将行为织入到业务流程中)
引入(introduction) 不修改代码,在运行期(runtime)将类动态添加一些方法或字段。

二、Spring中AOP的实现原理

Spring AOP实现的基石在于代理,也就是应用AOP后实际上是生成AOP代理对象,Spring中AOP代理及其依赖关系由IoC容器负责生成、管理。

代理对象=目标对象+切面处理(通知)

1. 代理

1.1 静态代理

静态代理产生于代码的编译阶段,一旦代码运行就不可改变;

// 接口
public interface IPerson {
  public void doSth();
}

// 接口实现
public class Person implements IPerson {
  public void doSth(){
    System.out.println("do sth");
  }
}

// 代理实现
public class PersonProxy {
  private IPerson person;

  public PersonProxy(IPerson person) {
    this.person = person;
  }

  public void doSth() {
    System.out.println("before do sth");
    person.doSth();
    System.out.println("after do sth");
  }
}
public static void main(String[] args) {
  PersonProxy personProxy = new PersonProxy(new Person());
  personProxy.doSth();
}
/*
result console:
before do sth
do sth
after do sth
*/

1.2 动态代理

这里特指JDK动态代理,区别与静态代理,动态代理产生于代码的运行时阶段。JDK动态代理利用了Java的反射机制,生成一个实现代理接口的类,调用具体方法由InvocationHandler来处理。这种动态代理需要依赖接口来实现。

public class PersonProxy implements InvocationHandler {
  private Object delegate;

  public Object bind(Object delegate) {
    this.delegate = delegate;
    // 指明类加载器、指明生成哪个对象的代理对象(接口指定)、指明Handler
    return Proxy.newProxyInstance(delegate.getClass().getClassLoader(), delegate.getClass().getInterfaces(), this);
  }

  public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
    Object result = null;
    try {
      System.out.println("before do sth");
      result = method.invoke(delegate, args);
      System.out.println("after do sth");
    } catch(Exception e) {
      throw e;
    }
    return result;
  }
}
public static void main(String[] args) {
  PersonProxy personProxy = new PersonProxy();
  IPerson iPerson = (IPerson) personProxy.bind(new Person());
  iPerson.doSth();
}
/*
result console:
before do sth
do sth
after do sth
*/

1.3 CGLIB

如果没有接口,动态代理可以借助CGLIB来实现,它可以用生成代理目标子类(因此不能代理final修饰的类)的方式来实现代理,而不是接口,规避来接口的局限性。

实现MethodInterceptor接口来实现。

public class PersonProxy implements MethodInterceptor {
  private Object delegate;
  public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
    System.out.println("before do sth");
    Object result = methodProxy.invokeSuper(method, args);
    System.out.println("after do sth");
    return result;
  }
  public static Person getProxyInstance() {
    Enhancer enhancer = new Enhancer();
    enhancer.setSuperclass(Person.class);
    enhancer.setCallback(new PersonProxy());
    return (Person) enhancer.create();
  }
}
public static void main(String[] args) {
  Person person = PersonProxy.getProxyInstance();
  person.doSth();
}
/*
result console:
before do sth
do sth
after do sth
*/

2. Spring AOP代理创建规则

Spring提供了两种方式来生成代理对象:JDKProxyCGLIB
使用方式由AopProxyFactory根据AdvisedSupport对象配置来决定。

代理默认创建规则:

  1. 如果目标类是接口,则使用Java动态代理创建AOP代理;
  2. 如果目标类不是接口,则使用Cglib生成代理;

三、在Spring中使用AOP

AOP编程步骤:

  1. 定义普通业务组件;
  2. 定义切入点(切入点和业务组件的对应关系可以是一对多);
  3. 定义增强处理,即为普通业务组件织入的动作;

1. 使用XML文件配置AOP

参考:Spring 中基于 AOP 的 XML架构

2. 使用注解配置AOP

参考:Spring 中基于 AOP 的 @AspectJ

四、总结

  1. AOP(Aspect Oriented Programming,面向切面编程),横向抽象的一种编程思想,是对OOP(Object Oriented Programming,面向对象编程)的补充和完善。
  2. Spring AOP实现的基石在于代理,也就是应用AOP后实际上是生成AOP代理对象,Spring中AOP代理及其依赖关系由IoC容器负责生成、管理。
  3. Spring中AOP的编程模型是定义组件、定义切入点、定义增强功能。

参考资料

  1. Spring3:AOP
  2. Spring AOP原理分析一次看懂
  3. Spring-aop 全面解析(从应用到原理)
  4. Spring的两种代理JDK和CGLIB的区别浅谈
  5. Spring 教程

Spring:AOP的更多相关文章

  1. Spring:AOP面向切面编程

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

  2. spring:AOP面向切面编程(注解)03

    使用注解写aop时最好使用环绕通知写 切面类: /** * 用于记录日志的工具类,它里面提供了公共的代码 */ @Component("logger") @Aspect //表示当 ...

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

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

  4. 理解Spring:AOP的原理及手动实现

    引入 到目前为止,我们已经完成了简易的IOC和DI的功能,虽然相比如Spring来说肯定是非常简陋的,但是毕竟我们是为了理解原理的,也没必要一定要做一个和Spring一样的东西.到了现在并不能让我们松 ...

  5. Spring:Aop before after afterReturn afterThrowing around 的原理

    在写这篇文章前,在网上看了一下大多数的文章,在说这一块时,都是用语言来表达的.before.after.afterReturn.afterThrowing 这四个用语言是可以说清楚的,但 around ...

  6. 使用spring:aop中修改增强方法中的参数

    大家都知道,在增强方法中,使用jp.getArgs()[index]可以获取传进来的参数,但是参数传进来之后,怎么改变它的值呢? 因为jp.getArgs()[index]获取到的只是数据的备份,所以 ...

  7. 深入浅出学习Spring框架(三):AOP 详解

    AOP的英文解释——AOPAspect Oriented Programming面向切面编程.主要目的是通过预编译方式和运行期动态代理实现在不修改源代码的情况下给程序动态统一添加功能的一种技术. 在反 ...

  8. Spring使用 --- 基本概念(二):AOP,面向方面编程

    Table of Contents 什么是面向方面编程 怎样使用 什么时候使用 好处 本文讲述sprint的第二个基本概念: AOP,即面向方面编程 什么是面向方面编程 软件项目中,日志系统等服务系统 ...

  9. Java框架spring 学习笔记(十二):aop实例操作

    使用aop需要在网上下载两个jar包: aopalliance.jar aspectjweaver.jar 为idea添加jar包,快捷键ctrl+shift+alt+s,打开添加jar包的对话框,将 ...

随机推荐

  1. HTML5 拖放实例

    <!DOCTYPE HTML><html><head><meta charset="utf-8"> <title>菜鸟教 ...

  2. python列表中的所有值转换为字符串,以及列表拼接成一个字符串

    >>> ls1 = ['a', 1, 'b', 2] >>> ls2 = [str(i) for i in ls1] >>> ls2 ['a', ...

  3. 前端——JavaScript之if语句

    4.1 if语句 如果……否则……  , 让程序出现分支 1        <script type="text/javascript"> 2           va ...

  4. C++ 线性搜索算法演示的代码

    将做工程过程中比较好的内容做个备份,下边代码段是关于C++ 线性搜索算法演示的代码. #include<iostream>#include<conio> int linears ...

  5. Promise.all处理多个异步请求

    一个前台页面需要请求2个rest接口获取数据,一个用于解析文件获取列名,一个查询数据库获得列值. 有很低的概率页面显示为空,刷新可能就有显示了. 使用Promise.all就解决了上面的问题,2部分数 ...

  6. Linux 系统报错 rcu_preempt detected stalls on CPUs/tasks

    说在前面的一些废话: 这是什么错误我不知道,为什么出现我不知道! 那为什么还要把他写出来了,只是因为这个错误遇到了,而且浪费了我很多时间和精力. 故事留给自己看,解决办法就是,重新升级一下Linux系 ...

  7. Spring4.0开始的泛型依赖

    参考资料: http://www.cnblogs.com/solverpeng/p/5687304.html 视频地址:https://edu.51cto.com/course/1956.html 一 ...

  8. Mysql优化批量插入数据

    最近为了测试项目,需要在Mysql中插入百万级测试数据,于是用到了批量插入,自己写了个简单的Spring Cloud项目. 开始时执行效率很慢,大概100条/秒,批次的大小也试过1000,2000,5 ...

  9. 生产者消费者synchronized wait notify

    package ProduceQueueProduce; import java.util.Queue; public class ProducerThread extends Thread { pu ...

  10. SpringMvc实现的简单原理

    1.浏览器发送请求 2.服务器执行servlet的(前端控制器)解析器 3.servlet通过(前端控制器)解析器拿到所有带有@Controller注解的类,并遍历类中的所有方法 4.将遍历的方法中带 ...