软件编程
位置:首页>> 软件编程>> java编程>> Spring AOP底层原理及代理模式

Spring AOP底层原理及代理模式

作者:把苹果咬哭的测试笔记  发布时间:2023-05-05 14:19:38 

标签:Spring,AOP,原理,代理

Spring AOP底层原理代理模式

一、什么是 AOP

AOP 就是面向切面编程,是 OOP(面向对象编程)的延续。

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

通俗一点说,不用修改原代码,可以给原代码增加新的功能。

二、AOP 底层原理

AOP 底层原理是使用 * 。

那代理是什么?有 * ,那是不是还有静态代理?

1. 什么是代理?

就是为一个目标对象提供一个代理对象,并由代理对象控制对目标对象的引用。使用代理对象,是为了在不修改目标对象的基础上,增强目标对象的业务逻辑。

比如目标对象 A,代理对象是 B。

  • 那么现在 B 对 A 进行引用,可以实现 A 有的功能。

  • 另外,B 还可以在自身进行一些新功能,最终不需要修改目标对象 A 。

而代理分为静态代理和 * ,区别是:

静态代理有真实的代理类存在,就是我们会代码中创建一个代理类,并在代理类的方法中调用目标对象的方法,以此来完成代理的工作。 * 的代理类没有在代码中创建一个代理类,而是在运行时在JVM里面创建代理对象。

2. 什么是静态代理

静态代理是有实实在在的代理类存在,并且和目标类实现相同的接口。

比如,有一个转账业务,现在希望给它增加功能,使在转账之前确认转账人身份,以及转账之后通知收款人。

(1) 接口 AccountServiceDao :

package com.pingguo.spring5.dao;
public interface AccountServiceDao {
   // 主业务逻辑,转账
   void transfer();
}

(2) 接口 AccountServiceDao 的实现类:

package com.pingguo.spring5.dao;
public class AccountServiceImpl implements AccountServiceDao {
   @Override
   public void transfer() {
       System.out.println("调用dao层,完成转账主业务.");
   }
}

(3) 代理类 AccountProxy :

package com.pingguo.spring5.proxy;
import com.pingguo.spring5.dao.AccountServiceDao;
public class AccountProxy implements AccountServiceDao {
   // 目标对象
   private AccountServiceDao target;
   public AccountProxy(AccountServiceDao target) {
       this.target = target;
   }
   /**
    *  代理方法,实现对目标方法的增强
    */
   @Override
   public void transfer() {
       before();
       target.transfer();
       after();
   }
   /**
    *  增强的功能,转账之前使用
    */
   private void before() {
       System.out.println("对转账人身份进行验证.");
   }
   /**
    *  增强的功能,转账之后使用
    */
   private void after() {
       System.out.println("转账完成,已通知收款人.");
   }
}

在代理类中:

  • 添加了添加了目标对象,并且有参构造方法里需要传入目标对象。

  • 代理方法里,调用了目标对象里的转账方法 target.transfer()。

  • before() 和 after() 则是 2个增强的方法,分别作用于 target.transfer() 的前面和后面。

(4) 运行测试新建一个测试方法,运行看下结果:

@Test
   public void testProxy() {
       // 创建目标对象
       AccountServiceDao target = new AccountServiceImpl();
       // 创建代理对象
       AccountProxy proxy = new AccountProxy(target);
       proxy.transfer();
   }
  • 这里先创建了目标对象

  • 再创建代理对象,并且把目标对象传入

  • 最后调用代理对象里的,被增强过的方法 transfer()。

结果:

对转账人身份进行验证.
调用dao层,完成转账主业务.
转账完成,已通知收款人.
Process finished with exit code 0

优点:

  • 效率高,因为所有的类都是已经编写完成的,使用的时候只需要取得代理对象并且执行即可。

  • 同时也可以实现对目标对象中指定的方法进行增强。

缺点:

  • 与目标类实现相同的接口代码,冗余。

  • 如果接口发生改变,代理类中的方法也要修改。

  • 代理类服务于一种类型的对象,如果要服务多类型的对象,那么要为每种类型的对象都生成代理类。

3. 什么是 *

与静态代理的硬编码方式相比, * 支持运行时动态生成代理对象这种方式。换句话说, * 并不存在代理类,代理对象直接由代理生成工具动态生成。

优点:

  • 用很少的代码对一个类的所有方法实现一样的增强效果。

  • 在编码时,代理逻辑与业务逻辑互相独立,各不影响,减少侵入,降低耦合。

缺点:

相对于静态代理,它不能增强其中的某一个方法。

对于 * ,针对于是否存在接口的情况下,又分为 2 种:

  • 有接口的情况下,使用 JDK * 。

  • 无接口的情况下,使用 CGLIB * 。

使用 JDK *

使用 JDK * ,创建的是接口实现类的代理对象,以此来实现功能增强。

现在不需要上面创建过的实际代理类了 。

接口,为了后面的一些知识点的说明,里面加个参数,转账的金额:

package com.pingguo.spring5.dao;
public interface AccountServiceDao {
   // 主业务逻辑,转账
   void transfer(int amount);
}

实现类:

package com.pingguo.spring5.dao;
public class AccountServiceImpl implements AccountServiceDao {
   @Override
   public void transfer(int amount) {
       System.out.println("调用dao层,完成转账主业务.金额:" + amount);
   }
}

在测试方法里,直接使用 * :

@Test
   public void testDynamicProxy() {
       // 创建目标对象
       AccountServiceDao target = new AccountServiceImpl();
       // 创建代理对象
       AccountServiceDao proxy = (AccountServiceDao) Proxy.newProxyInstance(
               target.getClass().getClassLoader(),  // 目标类使用的类加载器
               target.getClass().getInterfaces(),  // 目标类实现的接口
               new InvocationHandler() {  // 调用处理器
                   @Override
                   public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                       System.out.println("对转账人身份进行验证.");
                       Object res =  method.invoke(target, args);
                       System.out.println("转账完成,已通知收款人.");
                       return res;
                   }
               }
       );
       // 让代理工作
       proxy.transfer(10000);
   }

运行结果:

对转账人身份进行验证.
调用dao层,完成转账主业务.金额:10000
转账完成,已通知收款人.
Process finished with exit code 0

* 的过程:

  • 创建处理器 InvocationHandler实例。

  • 在调用目标对象时,会调用代理对象。

  • 代理对象去请求目标对象。invoke 方法就是调用目标对象的方法生成代理对象的过程。

  • 同时,在 invoke 方法中进行功能增强。

对于 invoke 中的 3 个参数,分别是:

  • Object proxy:代理对象,一般不会使用。

  • Method method:外面的代理对象调用的方法引用,这里引用的就是 transfer()

  • Object[] args:外面的代理对象调用的方法里面的参数,这里就是参数 amount。

使用 CGLIB *

CGLIB * 的原理是生成目标类的子类,这个子类对象就是代理对象,代理对象是被增强过的。

注意,不管有没有接口都可以使用 CGLIB * , 而不是只有在无接口的情况下才能使用。

示例就暂时不放了,因为我本地环境问题,有个报错始终未解决,后续再说,不影响继续学习 spring。

来源:https://blog.csdn.net/wessonlan/article/details/124812970

0
投稿

猜你喜欢

  • 在项目中我们肯定不能使用Spring自己生成的登录页面,而要用我们自己的登录页面,下面讲一下如何自定义登录页面,先看下配置<sec:h
  • 利用java8流的特性,我们可以实现list中多个元素的 属性求和 并返回。案例:有一个借款待还信息列表,其中每一个借款合同包括:本金、手续
  • 最近的项目在做socket通信报文解析的时候,用到了结构体与字节数组的转换;由于客户端采用C++开发,服务端采用C#开发,所以双方必须保证各
  • 结构体概念在C#中,结构体是值类型,一般适用于表示类似Point、Rectangle、Color的对象值类型能够降低对堆的管理、使用。降低垃
  • Android中的传递有两个方法,一个是Serializable,另一个是Parcelable。Serializable是J2SE本身就支持
  • Java集合是java提供的工具包,包含了常用的数据结构:集合、链表、队列、栈、数组、映射等。Java集合工具包位置是java.util.*
  • 一、事务的基本原理Spring事务的本质其实就是数据库对事务的支持,没有数据库的事务支持,spring是无法提供事务功能的。对于纯JDBC操
  • Mybatis条件if test使用枚举值1.正确package com.weather.weatherexpert.common.util
  • 在网上有非常多通过射线方式实现的人物行走控制脚本,可是假设仅仅是想通过键盘按键来控制的话。比方进行第三人称视角控制,事实上仅仅须要进行简单的
  • 需求:学生输入姓名和语文、数学、英语,编程求出总分和平均分,并在屏幕上显示XX的总分和平均分using System;using Syste
  • 本文实例讲述了Android编程实现的短信编辑器功能。分享给大家供大家参考,具体如下:修改短信数据库,从而生成任意手机号发送的短信。Andr
  • 前言面向切面编程,利用 AOP 可以对业务逻辑的各个部分进行隔离,从而使得业务逻辑各部分之间的耦合度降低,提高程序的可重用性,同时提高了开发
  • 1.概述本篇文章仅是Android小白在写一个小程序,内容仅供参考,有很多不足之处希望各位大神指出,文章末尾有整个项目的下载,不需要币,只求
  • 二维数组实现数字拼图,供大家参考,具体内容如下二维数组可以自己随意定义大小,通过方法判断来实现对所有的数字进行随机打乱,并可以通过移动来正确
  • 线程线程:对于所有需要等待的操作,例如移动文件,数据库和网络访问都需要一定的时间,此时就可以启动一个新的线程,同时完成其他任务。一个进程的多
  • 本文实例为大家分享了banner轮播图无限轮播效果的具体代码,供大家参考,具体内容如下效果展示第一步(权限配置)<uses-permi
  • Android 实现会旋转的饼状统计图实例代码最近在做一个项目,由于有需要统计的需要,于是就做成了下面饼状统计图。 下图是效果图: 大致思路
  • 一、前言前一篇文章已经详细介绍了如何使用Xposed框架编写第一个微信插件:摇骰子和猜拳 * 本文继续来介绍如何使用Xposed框架编写第
  • 上一篇文章: # Android 10 启动分析之Zygote篇 (三)紧接着上一篇文章的内容,我们从这篇文章开始来分析一下 SystemS
  • 同类型对象的比较三个维度去比较同一性相等性相似性样例引入想象一下这样的一个场景:小王去图书馆借了一本java核心技术卷1,如图不幸的是小王把
手机版 软件编程 asp之家 www.aspxhome.com