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

文章目录

    • 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

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

微信小程序 最新获取用户头像以及用户名

一.在小程序改版为了安全起见 使用用户填写来获取头像以及用户名 二.代码实现 <view class"login_box"><!-- 头像 --><view class"avator_box"><button wx:if"{{ !userInfo.avatarUrl }}" class"avatorbtn" op…

【Linux】进程的状态详解

进程的状态详解 一、各种状态的概念二、运行状态的详细介绍三、阻塞状态详解四、挂起状态和阻塞状态的关系五、观察各种状态在linux中的表示1.运行态R2.睡眠态S3.暂停态T4.深度睡眠状态D5.僵尸状态Z6.孤儿进程 一、各种状态的概念 为了弄明白正在运行的进程是什么意思&#xf…

python高级之简单爬虫实现

一、前言 场景1&#xff1a;一个网络爬虫&#xff0c;顺序爬取一个网页花了一个小时&#xff0c;采用并发下载就减少到了20分钟。 场景2&#xff1a;一个应用软件优化前每次打开网页需要3秒&#xff0c;采用异步并发提升到了200毫秒。 假设一个工程的工作量为100&#xff0c…

web——upload-labs——第十关——.空格.绕过

审计源码 这次先删除文件名左右的空格&#xff0c;然后又删除了我们文件末尾的.&#xff0c;其次将我们上传的文件名转换为小写&#xff0c;删除文件末尾的::$DATA&#xff0c;最后又删除了文件名左右两侧的空格 根据他的逻辑&#xff0c;我们可以构造文件名phpinfo.php. .就是…

Percona XtraBackup备份docker版本mysql 5.7

my.cnf配置文件 [client] default_character_setutf8[mysqld] # 数据存储目录&#xff08;必须手动指定&#xff09; datadir/var/lib/mysql/data# 字符集 collation_server utf8_general_ci character_set_server utf8 # 二进制日志 server-id1 log_bin/var/log/mysql/binl…

JavaWeb之Vue

前言 这一节讲Vue 1. Vue概述 这些都是DOM的操作 原来模型和视图不能实现同步变化&#xff0c;但是Vue就可以了 2. 快速入门 1. 2. <script src"js/vue.js"></script><div id"app"> <!-- 准备一个input输入框,绑定一个模…

汽车资讯新篇章:Spring Boot技术启航

4系统概要设计 4.1概述 本系统采用B/S结构(Browser/Server,浏览器/服务器结构)和基于Web服务两种模式&#xff0c;是一个适用于Internet环境下的模型结构。只要用户能连上Internet,便可以在任何时间、任何地点使用。系统工作原理图如图4-1所示&#xff1a; 图4-1系统工作原理…

Windows注册表基础学习

修改注册表让cmd ascii输出有颜色 reg add HKCU\Console /v VirtualTerminalLevel /t REG_DWORD /d 1 如何打开注册表编辑器 运行regedit 按下"Winr"组合键&#xff0c;在打开的"运行"对话框中输入"regedit"&#xff0c;单击"确定"…

C++ | Leetcode C++题解之第564题寻找最近的回文数

题目&#xff1a; 题解&#xff1a; using ULL unsigned long long;class Solution { public:vector<ULL> getCandidates(const string& n) {int len n.length();vector<ULL> candidates {(ULL)pow(10, len - 1) - 1,(ULL)pow(10, len) 1,};ULL selfPrefi…

Debezium-MySqlConnectorTask

文章目录 概要整体架构流程技术名词解释技术细节小结 概要 MySqlConnectorTask&#xff0c;用于读取MySQL的二进制日志并生成对应的数据变更事件 整体架构流程 技术名词解释 数据库模式&#xff08;Database Schema&#xff09; 数据库模式是指数据库中数据的组织结构和定义&…

【WPF】Prism学习(二)

Prism Commands 1.命令&#xff08;Commanding&#xff09; 1.1. ViewModel的作用&#xff1a; ViewModel不仅提供在视图中显示或编辑的数据&#xff0c;还可能定义一个或多个用户可以执行的动作或操作。这些用户可以通过用户界面&#xff08;UI&#xff09;执行的动作或操作…

如何实现主备租户的无缝切换 | OceanBase应用实践

对于DBA而言&#xff0c;确保数据库的高可用性、容灾等能力是其日常工作中需要持续思考和关注的重要事项。一方面&#xff0c;可以利用数据库自身所具备的功能来实现这些目标&#xff1b;若数据库本身不提供相应功能&#xff0c;DBA则需寻找其他工具来增强数据库的高可用性和容…

壁仞科技上市前最后一波 校招 社招 内推

随着美国大选结束&#xff0c;国内GPU 产业得到空前的的发展空间&#xff0c;国内芯片相关股票一片飘红。 国内大型 GPU厂商壁仞科技&#xff0c;摩尔线程等正紧锣密鼓地加紧上市。 GPGPU 芯片赛道来到了史无前例的红利点&#xff0c;抓住机会&#x1f4aa; 壁仞科技正在火热…

前端监控之sourcemap精准定位和还原错误源码

一、概述 在前端开发中&#xff0c;监控和错误追踪是确保应用稳定性和用户体验的重要环节。 随着前端应用的复杂性增加&#xff0c;JavaScript错误监控变得尤为重要。在生产环境中&#xff0c;为了优化加载速度和性能&#xff0c;前端代码通常会被压缩和混淆。这虽然提升了性…

使用Web Push Notifications提升用户参与度和留存率

&#x1f493; 博客主页&#xff1a;瑕疵的CSDN主页 &#x1f4dd; Gitee主页&#xff1a;瑕疵的gitee主页 ⏩ 文章专栏&#xff1a;《热点资讯》 使用Web Push Notifications提升用户参与度和留存率 使用Web Push Notifications提升用户参与度和留存率 使用Web Push Notifica…

量化选股日常操作日记-11-ai眼镜-润欣科技

用 微信小程序 梦想兔企业智能风险分析助手 &#xff0c;选择AI眼镜板块&#xff0c;挖掘了几个合适的股&#xff0c;分析下来感觉 润欣科技 比较安全些适合观察&#xff0c;几块到十几块波动&#xff0c;企业基本面也没有特别大问题。就是现在价位在周期波动高位&#xff0c;下…

【WPF】Prism学习(五)

Prism Commands 1.错误处理&#xff08;Error Handling&#xff09; Prism 9 为所有的命令&#xff08;包含AsyncDelegateCommand&#xff09;提供了更好的错误处理。 避免用try/catch包装每一个方法根据不同遇到的异常类型来提供特定的逻辑处理可以在多个命令之间共享错误处…

Intern大模型训练营(八):Llamaindex RAG 实践

1. 基于 LlamaIndex 构建自己的 RAG 知识库 首先在Intern Studio中申请30% A100的开发机。 进入开发机后&#xff0c;创建新的conda环境&#xff0c;命名为 llamaindex&#xff0c;在命令行模式下运行&#xff1a; conda create -n llamaindex python3.10 复制完成后&#…

台式电脑没有声音怎么办?台式电脑没有声音解决详解

台式电脑一般来说都是没有内置扬声器的&#xff0c;需要连接耳机或者是音响才可以播放音乐。那么如果遇到台式电脑没有声音的问题&#xff0c;我们也需要确认这些设备硬件有没问题&#xff0c;知道原因才可以进行处理。下面本文将为你介绍台式电脑没有声音的可能原因和解决方法…

vue2项目中在线预览csv文件

简介 希望在项目中&#xff0c;在线预览.csv文件&#xff0c;本以为插件很多&#xff0c;结果都只是支持excel&#xff08;.xls、.xlsx&#xff09;一到.csv就歇菜。。。 关于文件预览 vue-office&#xff1a;文档、 查看在线演示demo&#xff0c;支持docx、.xlsx、pdf、ppt…