如何理解 Spring 中的 AOP

一、AOP 的概述

  1. AOP(Aspect Oriented Programming):面向切面编程,通过预编译方式和运行期动态代理来实现程序功能的统一维护的一种技术。

  2. AOP是OOP(面向对象编程)的延续,是 Spring 框架中重要内容,是函数式编程的一种衍生范型。

  3. 利用AOP可以对业务逻辑的各个部分进行隔离,从而使得业务逻辑各部分之间的耦合度降低,提高程序的可重用性,同时提高了开发的效率。

  4. AOP采取横向抽取机制,取代了传统纵向继承体系重复性代码

    纵向继承。

  5. 经典应用场景:事务管理、性能监视、安全检查、缓存 、日志等。

  6. Spring AOP使用纯 Java 实现,不需要专门的编译过程和类加载器,在运行期通过代理方式向目标类织入增强代码。

  7. AspectJ是一个基于Java语言的AOP框架,Spring2.0开始,Spring AOP引入对Aspect的支持,AspectJ扩展了Java语言,提供了一个专门的编译器,在编译时提供横向代码的织入。

  8. Spring 中的 AOP 实现原理

    a、接口 + 实现类 :Spring采用 jdk 的动态代理Proxy。

    b、实现类:Spring 采用 cglib字节码增强。

    a、Aop底层将采用代理机制进行实现(最底层也是依赖反射)

二、AOP 实现案例

1、对 AOP 的理解(画图解释)

2、AOP 中通过 JDK动态代理简单案例演示

接口、实现类和切面类

public interface UserService {

    void addUser();

    void updateUser();

    int deleteUser(int id);
}
=========================================================================================
public class UserServiceImpl implements UserService { @Override
public void addUser() {
System.out.println("添加用户");
} @Override
public void updateUser() {
System.out.println("更新用户");
} @Override
public int deleteUser(int id) {
System.out.println("通过id删除用户");
return 1;
}
} 切面类
public class MyAspect { public void before(){
System.out.println("开启事务");
} public void after(){
System.out.println("提交事务");
}
}

JDK实现动态代理

public class MyBeanFactory {
// JDK实现动态代理
public static UserService createUserService() {
//1.创建目标对象target
final UserService userService = new UserServiceImpl(); //2.声明切面类对象
final MyAspect aspect = new MyAspect(); //3.把切面类2个方法应用于目标类
//3.1 创建JDK代理,拦截方法
UserService serviceProxy = (UserService) Proxy.newProxyInstance(
MyBeanFactory.class.getClassLoader(),
userService.getClass().getInterfaces(),
(proxy, method, args) -> {
//开启事务
aspect.before(); //方法返回值:业务方法的返回值
Object retObj = method.invoke(userService, args);
//System.out.println("拦截返回值:" + retObj); //提交事务
aspect.after();
return retObj;
}
);
return serviceProxy;
}
}

测试函数

public class AOPTest {

    public static void main(String[] args) {
UserService userService = MyBeanFactory.createUserService(); userService.deleteUser(1);
userService.addUser();
userService.updateUser();
}
}

测试结果如下所示:

开启事务
通过id删除用户
提交事务
<=====================>
开启事务
添加用户
提交事务
<=====================>
开启事务
更新用户
提交事务
<=====================>

从测试结果可以看出,每次在执行业务代码的时候,会拦截对应的方法,执行切面类。

重点:JDK 的动态代理是通过接口和实现类完成的。

在 debug 测试函数: UserService userService = MyBeanFactory.createUserService();可以看出直接得到的是代理对象,代理对象中就有实现的功能。

在 debug 测试函数:UserService userService = new UserServiceImpl();可以看出直接得到的是其实现类,没有代理。

感兴趣的同学可以将测试函数中代码替换成上面两种。看看测试结果,以便于更好理解 AOP 思想。

3、AOP 中通过 CGlib 动态代理简单案例演示

public class StudentService {

    void delete() {
System.out.println("删除用户");
} void add() {
System.out.println("添加用户");
} void update() {
System.out.println("更新用户");
}
}
public class MyBeanFactory {

    //  CGlib实现代理
public static StudentService createStudentService(){
//1.创建目标对象target
final StudentService studentService = new StudentService(); //2.声明切面类对象
final MyAspect aspect = new MyAspect(); //3.创建增强对象
Enhancer enhancer = new Enhancer();
//设置父类
enhancer.setSuperclass(studentService.getClass());
//设置回调【拦截】
enhancer.setCallback((MethodInterceptor) (proxy, method, args, methodProxy) -> { aspect.before(); Object retObj = methodProxy.invokeSuper(proxy,args);//解藕
System.out.println("拦截....."); aspect.after();
return retObj;
}); //创建代理对象
StudentService serviceProxy = (StudentService) enhancer.create();
//System.out.println("serviceProxy);
return serviceProxy;
}
}

测试函数

public class AOPTest {

    public static void main(String[] args) {
StudentService studentService = MyBeanFactory.createStudentService();
studentService.add();
System.out.println("<=====================>");
studentService.delete();
System.out.println("<=====================>");
studentService.update();
System.out.println("<=====================>");
}
}

测试结果如下所示:

开启事务
添加用户
拦截.....
提交事务
<=====================>
开启事务
删除用户
拦截.....
提交事务
<=====================>
开启事务
更新用户
拦截.....
提交事务
<=====================>

CGlib 代理重点总结

a、没有接口,只有实现类。
b、采用字节码增强框架 cglib,在运行时 创建目标类的子类,从而对目标类进行增强。

Spring 讲解(六)的更多相关文章

  1. Spring Boot(六):如何使用mybatis

    Spring Boot(六):如何使用mybatis orm框架的本质是简化编程中操作数据库的编码,发展到现在基本上就剩两家了,一个是宣称可以不用写一句SQL的hibernate,一个是可以灵活调试动 ...

  2. Spring第六篇【Spring AOP模块】

    前言 Spring的第五篇也算是AOP编程的开山篇了,主要讲解了代理模式-..本博文主要讲解Spring的AOP模块:注解方式和XML方式实现AOP编程.切入点表达式.. AOP的概述 Aop: as ...

  3. Spring(十六)之MVC框架

    MVC 框架教程 Spring web      MVC 框架提供了模型-视图-控制的体系结构和可以用来开发灵活.松散耦合的 web 应用程序的组件.MVC 模式导致了应用程序的不同方面(输入逻辑.业 ...

  4. Spring第六篇---AOP

    接着Spring第五篇讲 我们今天将叙述以下几个知识点 1 什么是AOP AOP 是一种思想  横向重复  纵向抽取 在软件业,AOP为Aspect Oriented Programming的缩写,意 ...

  5. Spring Boot2(六):使用Spring Boot整合AOP面向切面编程

    一.前言 众所周知,spring最核心的两个功能是aop和ioc,即面向切面和控制反转.本文会讲一讲SpringBoot如何使用AOP实现面向切面的过程原理. 二.何为aop ​ aop全称Aspec ...

  6. spring讲解

    今日先简单介绍一下Spring bean 的 5 种效果域,然后详细介绍 singleton 和 prototype 这两种最常用的效果域. JavaSpring Bean的五种效果域 效果域的种类 ...

  7. Spring讲解-----------表达式语言

    转自:https://blog.csdn.net/u011225629/article/details/47143083 5.1  概述5.1.1  概述       Spring表达式语言全称为“S ...

  8. Spring 讲解(一 )

    1.如何理解 Spring 框架 简单来说,Spring 是一个轻量级的控制反转(IoC)和面向切面(AOP)的容器框架. 因为以前写代码的时候,在使用类对象的时候,经常需要实例化创建(new 出来) ...

  9. spring boot(六):如何优雅的使用mybatis

    *:first-child{margin-top: 0 !important}.markdown-body>*:last-child{margin-bottom: 0 !important}.m ...

随机推荐

  1. 注解@requestBody自动封装复杂对象 (成功,自己的例子封装的不是一个复杂对象,只是一个简单的User对象,将jsp页面的name转成json字符串,再用JSON.stringify()传参就行了)

    注意:ajax向后台传值的时候,必须加上contentType:"application/json"; springmvc的注解@requestBody可以通过页面提交json来自 ...

  2. C# 调用windows时间同步服务获取准确时间

    //创建一个Daytime类代码如下:using System; using System.Collections; using System.Collections.Generic; using S ...

  3. Microsoft SQL Server(sql server 关系型数据库管理系统)

    sql server一般指Microsoft SQL Server 关系型数据库管理系统 Microsoft SQL Server 是一个全面的数据库平台,使用集成的商业智能 (BI)工具提供了企业级 ...

  4. webbench(web性能压力测试工具)

    在运维工作中,压力测试是一项很重要的工作.比如在一个网站上线之前,能承受多大访问量.在大访问量情况下性能怎样,这些数据指标好坏将会直接影响用户体验.但是,在压力测试中存在一个共性,那就是压力测试的结果 ...

  5. LOJ 2979 「THUSCH 2017」换桌——多路增广费用流

    题目:https://loj.ac/problem/2979 原来的思路: 优化连边.一看就是同一个桌子相邻座位之间连边.相邻桌子对应座位之间连边. 每个座位向它所属的桌子连边.然后每个人建一个点,向 ...

  6. [BZOJ1572] WorkScheduling

    中文题目:工作安排 原文题目:Work Scheduling 传送门 本题可以采用贪心 算法一:按工作时间排序,如果工作能按时完成的工作就按时完成,如果工作不能按时完成就把之前价值最小的工作和当前作比 ...

  7. 题解 P1017 【进制转换】

    我赶jio这个题难道是让我们写快写? 不管了,赶紧把咕咕咕了一万年的题解写出来. 这个题就是考察负进制和在mod意义下的除法运算的基础运算. (其实也没多大问题) 首先我们先假设一个原始数据\(num ...

  8. TypeScript躬行记(5)——类型兼容性

    TypeScript是一种基于结构类型的语言,可根据其成员来描述类型.以结构相同的Person接口和Programmer类为例,如下所示. interface Person { name: strin ...

  9. setTimeout,clearTimeout,setInterval,clearInteral详解

    设置定时器,在一段时间之后执行指定的代码,setTimeout与setInterval的区别在于setTimeout函数指定的代码仅执行一次 方法一: window.setTimeout(" ...

  10. HTML图片

    HTML图片 html图片 <img>标签可以在网页上插入一张图片,它是独立使用的标签,通过“src”属性定义图片的地址,通过“alt”属性定义图片加载失败时显示的文字,以及对搜索引擎和盲 ...