后端:Spring AOP原理--动态代理

news2024/11/19 18:36:29

文章目录

    • 1. Spring AOP底层原理
    • 2. 代理模式
    • 3. 静态代理
    • 4. 动态代理
      • 4.1 jdk 实现动态代理
      • 4.2 cglib 实现动态代理
      • 4.3 jdk、cglib动态代理两者的区别

1. Spring AOP底层原理

  • 创建容器 new applicationContext();
  • Spring把所有的Bean进行创建,进行依赖注入;
  • ioc.getBean(UserService.class)此时获取得到Bean并不是原本的UserService类,而是通过动态代理生成一个代理类,这个代理类继承自UserService类。

在这里插入图片描述

2. 代理模式

代理模式是一种比较好的设计模式;

  • 使用代理对象来增强目标对象(target object),这样就可以在不修改原目标对象的前提下,提供额外的功能操作,扩展目标对象的功能;
  • 将核心业务代码和非核心的公共代码分离解耦,提高代码的可维护性,让被代理类专注业务降低代码复杂度。
    • 被代理类专注业务;
    • 代理类非核心的公共代码;

通常使用代理实现比如拦截器、事务控制,还有测试框架 mock、用户鉴权、日志、全局异常处理等。

3. 静态代理

代理类:

package com.lize.demo.aop.static1;

public class CeoProxy extends Ceo{
    @Override
    public void meeting(String name) {
        if(name.equals("张三")){
            super.meeting(name);
        }else{
            System.out.println("登记:"+name);
        }
    }
}

被代理类:

package com.lize.demo.aop.static1;

public class Ceo {
    public void meeting(String name){
        System.out.println("接见客户:"+name);
    }
}

测试:

package com.lize.demo.aop.static1;


import org.junit.jupiter.api.Test;
public class TestProxy {
    @Test
    public void test(){
        Ceo ceo = new CeoProxy();
        ceo.meeting("张三");
        ceo.meeting("李四");
    }
}

运行结果:
在这里插入图片描述

使用静态代理的弊端:一个代理类只能代理一个类型。

4. 动态代理

4.1 jdk 实现动态代理

jdk自带的,不需要额外导入其他依赖;
Proxy类中使用频率最高的方法是:newProxyInstance(),Proxy这个方法主要用来生成一个代理对象。

public static Object newProxyInstance(ClassLoader loader,
	Class<?>[] interfaces,
	InvocationHandler h
)

三个参数分别表示的意思是:

  • loader:类加载器,用于加载代理对象,传入被代理类的类加载器;
  • interfaces:被代理类实现的一些接口;被代理的类需要实现接口;
  • h:实现了InvocationHandler接口的对象;
package com.lize.demo.aop.autoProxy;

public interface IUserService {
    void add();
}
package com.lize.demo.aop.autoProxy;

// 被代理的类
public class UserService implements IUserService{
    @Override
    public void add() {
        System.out.println("增加。。。");
    }
}
package com.lize.demo.aop.autoProxy;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;

public class MyHandler implements InvocationHandler {

    private Object target;

    public MyHandler(Object target){
        this.target = target;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {

        System.out.println("前置通知");
        // args 传递过来的参数
        Object res = method.invoke(target, args);

        System.out.println("后置通知");

        return res;
    }

}
package com.lize.demo.aop.autoProxy;


import org.junit.jupiter.api.Test;

import java.lang.reflect.Proxy;

public class TestProxy {

    @Test
    public void test(){

        IUserService userService = (IUserService) Proxy.newProxyInstance(
                UserService.class.getClassLoader(),
                UserService.class.getInterfaces(),
                new MyHandler(new UserService())
        );
        userService.add();
        System.out.println(userService.getClass());
    }
}

运行结果:
在这里插入图片描述

4.2 cglib 实现动态代理

package com.lize.demo.aop.autoProxy2;
// 被代理的类
public class UserService {

    public void add() {

        System.out.println("增加。。。");
    }
}
package com.lize.demo.aop.autoProxy2;


import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy;
import java.lang.reflect.Method;

// 做增强处理
public class MyCallback implements MethodInterceptor {

    private Object target;

    public MyCallback(Object target) {

        this.target = target;
    }

    @Override
    public Object intercept(Object o, Method method, Object[] args, MethodProxy proxy) throws Throwable {

        System.out.println("前置通知");

        Object res = proxy.invoke(target, args);

        System.out.println("后置通知");

        return res;
    }
}

package com.lize.demo.aop.autoProxy2;


import org.junit.jupiter.api.Test;
import org.springframework.cglib.proxy.Enhancer;

public class TestProxy {

    @Test
    public void test(){
        Enhancer enhancer = new Enhancer();
        // 设置被代理的类
        enhancer.setSuperclass(UserService.class);
        enhancer.setCallback(new MyCallback(new UserService()));
        UserService userService = (UserService) enhancer.create();
        // 代理的类
        userService.add();
        System.out.println(userService.getClass());
    }
}

在这里插入图片描述

4.3 jdk、cglib动态代理两者的区别

  • jdk动态代理只能代理实现了接口的类;而cglib可以代理未实现任何接口的类;
  • cglib动态代理是通过生成一个被代理类的子类来拦截被代理类的方法调用,因此不能代理声明为finnal类型的类和方法;
  • 在Spring中默认使用jdk动态代理,判断目标类是否实现了接口,如果实现了接口使用jdk动态代理,否则使用cglib;在Spring Boot中默认使用的是cglib动态代理。

在Spring中,如果想修改动态代理方式,可以通过注解的方式进行修改。

@EnableAspectJAutoProxy(proxyTargetClass = true) // cglib
@EnableAspectJAutoProxy(proxyTargetClass = false) // jdk

在Spring Boot中,如果想修改动态代理方式,可以通过在配置文件application.properties中添加配置即可。

spring.aop.proxy-target-class=false

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2243553.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

halcon3D gen_image_to_world_plane_map的图像高精度拼接技术

基于上一篇文章&#xff0c;对gen_image_to_world_plane_map有了深刻的理解 https://blog.csdn.net/Tianwen_running/article/details/143661157?fromshareblogdetail&sharetypeblogdetail&sharerId143661157&sharereferPC&sharesourceTianwen_running&s…

STM32 独立看门狗(IWDG)详解

目录 一、引言 二、独立看门狗的作用 三、独立看门狗的工作原理 1.时钟源 2.计数器 3.喂狗操作 4.超时时间计算 5.复位机制 四、独立看门狗相关寄存器 1.键寄存器&#xff08;IWDG_KR&#xff09; 2.预分频寄存器&#xff08;IWDG_PR&#xff09; 3.重载寄存器&…

《探索 Spring 核心容器:Bean 的奇妙世界》

一、Spring 核心容器与 Bean 的关系 Spring 核心容器是 Spring 框架的重要组成部分&#xff0c;负责管理和组织应用程序中的对象&#xff0c;而 Bean 则是构成应用程序主干并由 Spring IoC 容器管理的对象&#xff0c;二者紧密相连。 Spring 的核心容器由多个模块组成&#xf…

JFlash添加自定义MCU型号

1.打开安装路径 2.在Devices里创建你想添加的MCU的文件夹并把FLM文件放入 3.Jlink目录里找到JLinkDevices.xml文件 4.修改 <!-- --><!-- G32 --><!-- --><!-- --><!-- G32F103 --><!-- --><Device><ChipIn…

Linux中系统的延迟任务及定时任务

一、延时任务 at 命令&#xff0c;即用即消 如 at 11&#xff1a;30 rm -rf /mnt/* ctrld运行 &#xff08;过一秒即可执行&#xff09; -v 使用较明显的时间格式&#xff0c;列出at调度中的任务列表 -l 可列出目前系统上面的所有该用户的at调度 -c 可以列出后面接…

通过shell脚本分析部署nginx网络服务

通过shell脚本分析部署nginx网络服务 1.接收用户部署的服务名称 [rootlocalhost xzy]# vim 1.sh [rootlocalhost xzy]# chmod x 1.sh [rootlocalhost xzy]# ./1.sh2.判断服务是否安装 已安装&#xff1b;自定义网站配置路径为/www&#xff1b;并创建共享目录和网页文件&…

使用PSpice进行第一个电路的仿真

1、单击【开始】菜单&#xff0c;选择【OrCAD Capture CIS Lite】。 2、单击【File】>【New】>【Project】。 3、①填入Name下面的文本框&#xff08;提示&#xff1a;项目名称不要出现汉字&#xff09;&#xff1b; ②选择【Analog or Mixed A/D】&#xff1b; ③单击【…

CentOS网络配置

上一篇文章&#xff1a;VMware Workstation安装Centos系统 在CentOS系统中进行网络配置是确保系统能够顺畅接入网络的重要步骤。本文将详细介绍如何配置静态IP地址、网关、DNS等关键网络参数&#xff0c;以帮助需要的人快速掌握CentOS网络配置的基本方法和技巧。通过遵循本文的…

【unity小技巧】unity最全的性能优化方案分享以及如何进行性能测试(2024/11/11更新)

文章目录 前言一、性能分析软件1、Draw Call什么是Draw Call如何查看Draw Call数量 2、分析帧调试器3、Statistics统计面板 二、优化手段1、关于图集、材质、层级的处理&#xff0c;减少DrawCall2、批处理3、音乐处理4、减少沉余资源和重复资源5、渲染优化&#xff08;GPU&…

[STM32]从零开始的STM32 HAL库环境搭建

一、前言 之前在搭建STM32的标准库环境时就告诉过大家&#xff0c;开发STM32的方式主要有三种。一种是最原始但是效率最高的寄存器开发&#xff0c;另一种是效率仅次于寄存器难度相对较低的标准库开发&#xff0c;最后一种是最为简单但是程序效率最低的HAL库开发。如果对于初学…

阅读2020-2023年《国外军用无人机装备技术发展综述》笔记_技术趋势

目录 文献基本信息 序言 1 发展概况 2 重点技术发展 2.1 人工智能技术 2.1.1 应用深化 2.1.2 作战效能提升 2.2 航空技术 2.2.1螺旋桨设计创新 2.2.2 发射回收技术进步 2.3 其他相关技术 2.3.1 远程控制技术探 2.3.2 云地控制平台应用 3 装备系统进展 3.1 无人作…

python爬虫(二)爬取国家博物馆的信息

import requests from bs4 import BeautifulSoup# 起始网址 url https://www.chnmuseum.cn/zx/xingnew/index_1.shtml # 用于存储所有数据 all_data [] page 1 global_index 1 # 定义全局序号变量并初始化为1 while True:html_url requests.get(url).textif requests.get…

FPGA 第6讲 简单组合逻辑多路选择器

时间&#xff1a;2024.11.11-11.14 一、学习内容 1.组合逻辑 组合逻辑是VerilgHDL设计中一个重要组成部分。从电路本质上讲&#xff0c;组合逻辑电路的特点是输出信号只是当前时刻输入信号的函数&#xff0c;与其他时刻的输入状态无关&#xff0c;无存储电路&#xff0c;也没…

性能超越Spark 13.3 倍,比某MPP整体快数十秒 | 多项性能指标数倍于主流开源引擎 | 云器科技发布性能测试报告

云器Lakehouse正式发布性能测试报告 &#x1f3c5;离线批处理&#xff1a;在复杂批处理任务中&#xff0c;云器Lakehouse相较Spark表现出13.31倍性能提升。 &#x1f3c5;即席查询&#xff1a;在交互式分析场景下&#xff0c;云器Lakehouse相较Trino表现出9.84倍性能提升。 &am…

Frida反调试对抗系列(四)百度加固

本文只是交流技术&#xff0c;如有侵权请联系我删除。 知识星球&#xff1a;https://t.zsxq.com/kNlj4 前言&#xff1a; 上一篇文章我们提到 我们使用github开源魔改好的frida server 但是仍然有一些厂商的server不能通过&#xff0c;那么这篇文章针对百度加固 进行快速通…

利用redis的key失效监听器KeyExpirationEventMessageListener作任务定时提醒功能

某需求&#xff1a; 要求在任务截止日期的前3天时&#xff0c;系统自动给用户发一条消息提醒。 用定时任务的话感觉很不舒服。间隔时间不好弄。不能精准卡到那个点。 由于系统简单&#xff0c;没有使用消息列队&#xff0c;也不能使用延时队列来做。 用Timer的话开销还挺大的&a…

通过MongoDB Atlas 实现语义搜索与 RAG——迈向AI的搜索机制

目录 通过MongoDB Atlas 实现语义搜索与 RAG——迈向AI的搜索机制 一、引言 二、语义搜索与 MongoDB Atlas 的背景 三、MongoDB Atlas 的向量搜索功能 1. 向量搜索的实现方式 2. 典型操作示例 四、RAG 在 MongoDB Atlas 的应用 1、RAG是什么 2、RAG 的实现过程 3、RA…

【graphics】图形绘制 C++

众所周知&#xff0c;周知所众&#xff0c;图形绘制对于竞赛学僧毫无用处&#xff0c;所以这个文章&#xff0c;专门对相关人员教学&#xff08;成长中的码农、高中僧、大学僧&#xff09;。 他人经验教学参考https://blog.csdn.net/qq_46107892/article/details/133386358?o…

Excel使用-弹窗“此工作簿包含到一个或多个可能不安全的外部源的链接”的发生与处理

文章目录 前言一、探讨问题发生原因1.引入外部公式2.引入外部数据验证二、问题现象排查及解决1.排查公式2.排查数据验证3.特殊处理方式总结前言 作为一种常用的办公软件,Excel被大家所熟知。尽管使用了多年,有时候在使用Excel时候也会发生一些不太常见的现象,需要用心核查下…

递归(3)----力扣40组合数2,力扣473火柴拼正方形

给定一个候选人编号的集合 candidates 和一个目标数 target &#xff0c;找出 candidates 中所有可以使数字和为 target 的组合。 candidates 中的每个数字在每个组合中只能使用 一次 。 注意&#xff1a;解集不能包含重复的组合。 示例 1: 输入: candidates [10,1,2,7,6,1…