当前位置: 首页 > news >正文

Spring面试重点(三)——AOP循环依赖

Spring面试重点

AOP

  • 前置通知(@Before):在⽬标⽅法运行之前运行;
  • 后置通知(@After):在⽬标⽅法运行结束之后运行;
  • 返回通知(@AfterReturning):在⽬标⽅法正常返回之后运行;
  • 异常通知(@AfterThrowing):在⽬标⽅法出现异常是运行;
  • 环绕通知(@Around):手动推荐⽬标⽅法运行(proceedingJoinPoint.proceed())。

通用AOP日志切面类

<!-- springboot-aop 技术 -->
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-aop</artifactId>
</dependency>
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;import java.util.Arrays;/*** Title:通用日志切面* Description:* @author WZQ* @version 1.0.0* @date 2020/12/1*/
@Aspect
public class LogAspects {/*** 公共的切⼊入点表达式* 1、本类引⽤* 2、其他的切⾯引⽤* @author wzq* @date 2018/11/1*/@Pointcut(value = "execution(public int com.wzq.spring.study.service.CalcService.*(..))")public void pointCut() {}/*** 前置通知* pointCut切点指定方法* @param joinPoint joinPoint参数⼀一定要出现在参数列列表第⼀一位,放在后⾯面会报错*/@Before(value = "pointCut()")public void logStart(JoinPoint joinPoint) {String methodName = joinPoint.getSignature().getName();Object[] args = joinPoint.getArgs();System.out.println("@Before-->方法前,前置通知" + ",方法名:" + methodName + ",参数列列表是:" + Arrays.toString(args));}/*** 后置通知*/@After(value = "pointCut()")public void logEnd() {System.out.println("@After-->方法后,后置通知");}/*** 返回通知* @param joinPoint* @param result*/@AfterReturning(value = "pointCut()", returning = "result")public void logReturn(JoinPoint joinPoint, Object result) {String methodName = joinPoint.getSignature().getName();System.out.println("@AfterReturning-->返回通知,方法名:" + methodName + ",计算结果:" + result);}/*** 异常通知* @param joinPoint* @param exception*/@AfterThrowing(value = "pointCut()", throwing = "exception")public void logException(JoinPoint joinPoint, Exception exception) {String methodName = joinPoint.getSignature().getName();System.out.println("@AfterThrowing-->异常通知,方法名:" + methodName + ",异常信息:" + exception);}/*** 环绕通知* @param proceedingJoinPoint* @return* @throws Throwable*/@Around(value = "pointCut()")public Object around(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {Object retValue = null;System.out.println("@Around-->我是环绕通知之前AAA");retValue = proceedingJoinPoint.proceed();System.out.println("@Around-->我是环绕通知之后BBB");return retValue;}}
import com.wzq.spring.study.service.CalcService;
import com.wzq.spring.study.service.impl.CalcServiceImpl;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.EnableAspectJAutoProxy;/*** aop* 在程序运⾏期间动态的将某段代码切⼊到指定⽅方法指定位置进⾏运行的编程⽅式* '@EnableAspectJAutoProxy':开启基于注解的aop动态代理** @author wzq* @date 2018/11/1*/
@Configuration
@EnableAspectJAutoProxy
public class ConfigOfAOP {/*** 业务逻辑类加⼊入容器中* @author wzq* @date 2018/11/1*/@Beanpublic CalcService calculator() {return new CalcServiceImpl();}/*** 切面类加⼊入容器中* @author wzq* @date 2018/11/1*/@Beanpublic LogAspects logAspects() {return new LogAspects();}
}//也可以不需要此类,直接在切面类LogAspects加@Component注解注入容器即可,因为配置了切点

aop注解执行顺序

业务逻辑:

public class CalcServiceImpl implements CalcService {@Overridepublic int div(int x, int y) {int result = x / y;System.out.println("=========>CalcServiceImpl被调用了,我们的计算结果:"+result);return result;}}

测试

@Resourceprivate CalcService calcService;@Testvoid aopTest1() {System.out.println("spring版本:"+ SpringVersion.getVersion()+"\t"+"SpringBoot版本:"+ SpringBootVersion.getVersion());System.out.println();calcService.div(10,2);}

spring5.2.8后正常顺序和异常顺序(注意:实际是SpringBoot2.3.3版本之后):

spring版本:5.2.8.RELEASE	SpringBoot版本:2.3.3.RELEASE@Around-->我是环绕通知之前AAA
@Before-->方法前,前置通知,方法名:div,参数列列表是:[10, 2]
=========>CalcServiceImpl被调用了,我们的计算结果:5
@AfterReturning-->返回通知,方法名:div,计算结果:5
@After-->方法后,后置通知
@Around-->我是环绕通知之后BBB@Around-->我是环绕通知之前AAA
@Before-->方法前,前置通知,方法名:div,参数列列表是:[10, 0]
@AfterThrowing-->异常通知,方法名:div,异常信息:java.lang.ArithmeticException: / by zero
@After-->方法后,后置通知java.lang.ArithmeticException: / by zero

spring4,spring5前期正常顺序和异常顺序:

spring版本:4.3.13.RELEASE	SpringBoot版本:1.5.9.RELEASE@Around-->我是环绕通知之前AAA
@Before-->方法前,前置通知,方法名:div,参数列列表是:[10, 2]
=========>CalcServiceImpl被调用了,我们的计算结果:5
@Around-->我是环绕通知之后BBB
@After-->方法后,后置通知
@AfterReturning-->返回通知,方法名:div,计算结果:5spring版本:5.2.2.RELEASE	SpringBoot版本:2.2.2.RELEASE@Around-->我是环绕通知之前AAA
@Before-->方法前,前置通知,方法名:div,参数列列表是:[10, 2]
=========>CalcServiceImpl被调用了,我们的计算结果:5
@Around-->我是环绕通知之后BBB
@After-->方法后,后置通知
@AfterReturning-->返回通知,方法名:div,计算结果:5spring版本:4.3.13.RELEASE	SpringBoot版本:1.5.9.RELEASE@Around-->我是环绕通知之前AAA
@Before-->方法前,前置通知,方法名:div,参数列列表是:[10, 0]
@After-->方法后,后置通知
@AfterThrowing-->异常通知,方法名:div,异常信息:java.lang.ArithmeticException: / by zerojava.lang.ArithmeticException: / by zero

在这里插入图片描述

Spring循环依赖

循环依赖:多个bean之间相互依赖,形成了一个闭环。 比如:A依赖于B、B依赖于c、c依赖于A

通常来说,如果问spring容器内部如何解决循环依赖, 一定是指默认的单例Bean中,属性互相引用的场景

也就是说,Spring的循环依赖,是Spring容器注入时候出现的问题,类似死锁现象

在这里插入图片描述

官网说明:https://docs.spring.io/spring-framework/docs/current/spring-framework-reference/core.html#beans

在这里插入图片描述

官网可知,解决循环依赖使用setter注入bean,不能使用构造方法注入bean。

我们AB循环依赖问题只要A的注入方式是setter且singleton, 就不会有循环依赖问题

spring容器循环依赖报错演示BeanCurrentlylnCreationException

循环依赖现象在Spring容器中 注入依赖的对象,有2种情况,构造器方式注入依赖和以set方式注入依赖

构造器方式注入

无法解决循环依赖问题,构造器注入没有办法解决循环依赖, 你想让构造器注入支持循环依赖,是不存在的

@Component
public class ServiceA {private ServiceB serviceB;public ServiceA(ServiceB serviceB) {this.serviceB = serviceB;}
}
@Component
public class ServiceB {private ServiceA serviceA;public ServiceB(ServiceA serviceA) {this.serviceA = serviceA;}
}
/*** 通过构造器的方式注入依赖,构造器的方式注入依赖的bean,下面两个bean循环依赖** 测试后发现,构造器循环依赖是无法解决的*/
public class ClientConstructor {public static void main(String[] args) {//A构造函数依赖B注入,B构造函数依赖A注入,一直反复,无法结束new ServiceA(new ServiceB(new ServiceA(new ServiceB()))); ....}
}

set方式注入

不会报错

@Component
public class ServiceA {private ServiceB b;public ServiceB getB() {return b;}public void setB(ServiceB b) {this.b = b;System.out.println("A 里面设置了B");}}
@Component
public class ServiceB {private ServiceA a;public ServiceA getA() {return a;}public void setA(ServiceA a) {this.a = a;System.out.println("B 里面设置了A");}}
public class ClientSet {public static void main(String[] args) {//创建serviceAServiceA serviceA = new ServiceA();//创建serviceBServiceB serviceB = new ServiceB();//将serviceA注入到serviceB中serviceB.setServiceA(serviceA);//将serviceB注入到serviceA中serviceA.setServiceB(serviceB);}
}

spring容器

默认的单例(singleton)的set方式注入场景是支持循环依赖的,不报错

原型(Prototype)的场景是不支持循环依赖的,报错,多例下会报循环依赖异常BeanCurrentlylnCreationException

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/contexthttp://www.springframework.org/schema/context/spring-context.xsdhttp://www.springframework.org/schema/aophttp://www.springframework.org/schema/aop/spring-aop.xsdhttp://www.springframework.org/schema/tx"><!--1.spring容器默认的单例模式可以解决循环引用,单例默认支持2.spring容器原型依赖模式scope="prototype"多例模式下不能解决循环引用--><!--depends-on 的意思就是当前这个bean如果要完成,先看depends-on指定的bean是否已经完成了初始化--><!--scope="prototype"代表每次都要新建一次对象--><bean id="a" class="com.wzq.spring.study.service.impl.ServiceA" scope="singleton"><property name="b" ref="b"/></bean><bean id="b" class="com.wzq.spring.study.service.impl.ServiceB" scope="singleton"><property name="a" ref="a"/></bean></beans>
/*** nested exception is org.springframework.beans.factory.BeanCurrentlyInCreationException:* Error creating bean with name 'a': 578624778* Requested bean is currently in creation: Is there an unresolvable circular reference?*** 只有单例的bean会通过三级缓存提前暴露来解决循环依赖的问题,因为单例的时候只有一份,随时复用,那么就放到缓存里面* 而多例的bean,每次从容器中获取都是一个新的对象,都会重新创建, * 所以非单例的bean是没有缓存的,不会将其放到三级缓存中。*/
@Test
public void deTest() {    ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");ServiceA a = context.getBean("a", ServiceA.class);   ServiceB b = context.getBean("b", ServiceB.class);System.out.println(a); System.out.println(b);
}

spring三级缓存

DefaultSingletonBeanRegistry(re zi si g redʒɪstri)

所谓的三级缓存其实就是spring容器内部用来解决循环依赖问题的三个map

在这里插入图片描述

  • 第一级缓存(也叫单例池)singletonObjects:存放已经经历了完整生命周期的Bean对象
  • 第二级缓存: earlySingletonObjects,存放早期暴露出来的Bean对象,Bean的生命周期未结束(属性还未填充完整)
  • 第三级缓存: Map<String, ObiectFactory<?>> singletonFactories,存放可以生成Bean的工厂

在这里插入图片描述

spring源码分析

实例化/初始化

实例化是堆内存中申请一块内存空间,初始化是属性填充

spring利用单例set注入,解决循环依赖的三级缓存+四大方法

在这里插入图片描述

四大方法:

  1. getSingleton:希望从容器里面获得单例的bean,没有的话
  2. doCreateBean: 没有就创建bean
  3. populateBean: 创建完了以后,要填充属性
  4. addSingleton: 填充完了以后,再添加到容器进行使用

三级缓存:

  1. 第一层singletonObjects存放的是已经初始化好了的Bean,
  2. 第二层earlySingletonObjects存放的是实例化了,但是未初始化的Bean
  3. 第三层singletonFactories存放的是FactoryBean。假如A类实现了FactoryBean,那么依赖注入的时候不是A类,而是A类产生的Bean

在这里插入图片描述

在这里插入图片描述

三级缓存简单理解,AB单例依赖set注入

  1. A创建过程中需要B,于是A将自己放到三级缓存里面,去实例化B
  2. B实例化的时候发现需要A,于是B先查一级缓存,没有,再查二级缓存,还是没有,再查三级缓存,找到了A,然后把三级缓存里面的这个A放到二级缓存里面(实例,但未初始化),并删除三级缓存里面的A
  3. B顺利初始化完毕,将自己放到一级缓存里面(此时B里面的A依然是创建中状态),然后回来接着创建A,此时B已经创建结束,直接从一级缓存里面拿到B,然后完成创建,并将A自己放到一级缓存里面。

总结spring解决循环依赖

Spring创建bean主要分为两个步骤,创建原始bean对象,接着去填充对象属性和初始化。

每次创建bean之前,我们都会从缓存中查下有没有该bean,因为是单例,只能有一个。

当我们创建 beanA的原始对象后,并把它放到三级缓存中,接下来就该填充对象属性了,这时候发现依赖了beanB,接着就又去创建beanB,同样的流程,创建完 beanB填充属性时又发现它依赖了beanA又是同样的流程。

不同的是:
这时候可以在三级缓存中查到刚放进去的原始对象beanA,所以不需要继续创建,用它注入beanB,完成beanB的创建。

既然 beanB创建好了,所以beanA就可以完成填充属性的步骤了,接着执行剩下的逻辑,闭环完成

在这里插入图片描述

Spring解决循环依赖依靠的是Bean的“中间态"这个概念,而这个中间态指的是已经实例化但还没初始化的状态……>半成品。

实例化的过程又是通过构造器创建的,如果A还没创建好出来怎么可能提前曝光,所以构造器的循环依赖无法解决。

Spring为了解决单例的循环依赖问题,使用了三级缓存
其中一级缓存为单例池( singletonObjects)
二级缓存为提前曝光对象( earlySingletonObjects)
三级缓存为提前曝光对象工厂( singletonFactories)。

假设A、B循环引用,实例化A的时候就将其放入三级缓存中,接着填充属性的时候,发现依赖了B,同样的流程也是实例化后放入三级缓存,接着去填充属性时又发现自己依赖A,这时候从缓存中查找到早期暴露的A,没有AOP代理的话,直接将A的原始对象注入B,完成B的初始化后,进行属性填充和初始化,这时候B完成后,就去完成剩下的A的步骤,如果有AOP代理,就进行AOP处理获取代理后的对象A,注入B,走剩下的流程。

源码流程图如下:

在这里插入图片描述

debug步骤–》Spring解决循环依赖过程

  1. 调用doGetBean()方法,想要获取beanA,于是调用getSingleton()方法从缓存中查找beanA
  2. 在getSingleton()方法中,从一级缓存中查找,没有,返回null
  3. doGetBean()方法中获取到的beanA为null,于是走对应的处理逻辑,调用getSingleton()的重载方法(参数为ObjectFactory的)
  4. 在getSingleton()方法中,先将beanA_name添加到一个集合中,用于标记该bean正在创建中。然后回调匿名内部类的creatBean方法
  5. 进入AbstractAutowireCapableBeanFactory#doCreateBean,先反射调用构造器创建出beanA的实例,然后判断。是否为单例、是否允许提前暴露引用(对于单例一般为true)、是否正在创建中〈即是否在第四步的集合中)。判断为true则将beanA添加到【三级缓存】中
  6. 对beanA进行属性填充,此时检测到beanA依赖于beanB,于是开始查找beanB
  7. 调用doGetBean()方法,和上面beanA的过程一样,到缓存中查找beanB,没有则创建,然后给beanB填充属性
  8. 此时beanB依赖于beanA,调用getsingleton()获取beanA,依次从一级、二级、三级缓存中找,此时从三级缓存中获取到beanA的创建工厂,通过创建工厂获取到singletonObject,此时这个singletonObject指向的就是上面在doCreateBean()方法中实例化的beanA
  9. 这样beanB就获取到了beanA的依赖,于是beanB顺利完成实例化,并将beanA从三级缓存移动到二级缓存中
  10. 随后beanA继续他的属性填充工作,此时也获取到了beanB,beanA也随之完成了创建,回到getsingleton()方法中继续向下执行,将beanA从二级缓存移动到一级缓存中

相关文章:

Spring面试重点(三)——AOP循环依赖

Spring面试重点 AOP 前置通知&#xff08;Before&#xff09;&#xff1a;在⽬标⽅法运行之前运行&#xff1b;后置通知&#xff08;After&#xff09;&#xff1a;在⽬标⽅法运行结束之后运行&#xff1b;返回通知&#xff08;AfterReturning&#xff09;&#xff1a;在⽬标…...

计算机网络之HTTP04ECDHE握手解析

DH算法 离散读对数问题是DH算法的数学基础 &#xff08;1&#xff09;计算公钥 &#xff08;2&#xff09;交换公钥&#xff0c;并计算 对方公钥^我的私钥 mod p 离散对数的交换幂运算交换律使二者算出来的值一样&#xff0c;都为K k就是对称加密的秘钥 2. DHE算法 E&#…...

【MySQL数据库】主从复制原理和应用

主从复制和读写分离1. 主从复制的原理2. 主从复制的环境配置2.1 准备好数据库服务器2.2 配置master2.3 配置slave2.4 测试3. 主从复制的应用——读写分离3.1 读写分离的背景3.2 Sharding-JDBC介绍3.3 Sharding-JDBC使用步骤1. 主从复制的原理 MySQL主从复制是一个异步的过程&a…...

复现随记~

note(美团2022) 比较简单的越界漏洞&#xff0c;堆本身并没有什么漏洞&#xff0c;而且保护并没全开&#xff0c;所以逆向思维。必然是ROP类而非指针类&#xff0c;故我们着重注意unsigned int等无符号数前后是否不一致 int __fastcall edit(__int64 a1) {int idx; // [rsp14…...

【计组】设计大型DMP系统--《深入浅出计算机组成原理》(十四)

目录 一、DMP&#xff1a;数据管理平台 二、MongoDB 真的万能吗 三、关系型数据库&#xff1a;不得不做的随机读写 &#xff08;一&#xff09;Cassandra&#xff1a;顺序写和随机读 1、Cassandra 的数据模型 2、Cassandra 的写操作 3、Cassandra 的读操作 &#xff08…...

66 使用注意力机制的seq2seq【动手学深度学习v2】

66 使用注意力机制的seq2seq【动手学深度学习v2】 深度学习学习笔记 学习视频&#xff1a;https://www.bilibili.com/video/BV1v44y1C7Tg/?spm_id_from…top_right_bar_window_history.content.click&vd_source75dce036dc8244310435eaf03de4e330 在机器翻译时&#xff0c;…...

NextJS(ReactSSR)

pre-render&#xff1a; 预渲染 1. 静态化 发生的时间&#xff1a;next build 1). 纯静态化 2). SSG: server static generator getStaticProps: 当渲染组件之前会运行 生成html json //该函数只可能在服务端运行 //该函数运行在组件渲染之前 //该函数只能在build期间运…...

JointBERT代码复现详解【上】

BERT for Joint Intent Classification and Slot Filling代码复现【上】 源码链接&#xff1a;JointBERT源码复现&#xff08;含注释&#xff09; 一、准备工作 源码架构 data&#xff1a;存放两个基准数据集&#xff1b;model&#xff1a;JointBert模型的实现&#xff1b…...

进程间通信(上)

进程间通信&#xff08;上&#xff09;背景进程间通信目的进程间通信发展进程间通信分类管道什么是管道匿名管道实例代码简单的匿名管道实现一个父进程控制单个子进程完成指定任务父进程控制一批子进程完成任务&#xff08;进程池&#xff09;用fork来共享管道站在文件描述符角…...

【Unity3D】Unity 3D 连接 MySQL 数据库

1.Navicat准备 test 数据库&#xff0c;并在test数据库下创建 user 数据表&#xff0c;预先插入测试数据。 2.启动 Unity Hub 新建一个项目&#xff0c;然后在Unity编辑器的 Project视图 中&#xff0c;右击新建一个 Plugins 文件夹将连接 MySQL的驱动包 导入&#xff08;附加驱…...

vue通用后台管理系统

用到的js库 遇到的问题 vuex和 localStorage区别 vuex在内存中&#xff0c;localStorage存在本地localStorage只能存储字符串类型数据&#xff0c;存储对象需要JSON.stringify() 和 parse()…读取内存比读取硬盘速度要快刷新页面vuex数据丢失&#xff0c;localStorage不会vuex…...

IDEA设置只格式化本次迭代变更的代码

趁着上海梅雨季节&#xff0c;周末狠狠更新一下。平常工作在CR的时候&#xff0c;经常发现会有新同事出现大量代码变更行..一看原因竟是在格式化代码时把历史代码也格式化掉了这样不仅坑了自己&#xff08;覆盖率问题等&#xff09;&#xff0c;也可能会影响原始代码责任到人&a…...

算法训练——剑指offer(Hash集合问题)

摘要 数据结构中有一个用于存储重要的数据结构&#xff0c;它们就是HashMap,HasSet&#xff0c;它典型特征就是存储key:value键值对。在查询制定的key的时候查询效率最高O(1)。Hashmap&#xff0c;HasSet的底层结构是如图所示。它们的区别就是是否存在重复的元素。 二、HashMa…...

Element UI框架学习篇(七)

Element UI框架学习篇(七) 1 新增员工 1.1 前台部分 1.1.1 在vue实例的data里面准备好需要的对象以及属性 addStatus:false,//判断是否弹出新增用户弹窗dailog,为true就显示depts:[],//部门信息mgrs:[],//上级领导信息jobs:[],//工作岗位信息//新增用户所需要的对象newEmp:…...

【项目实战】32G的电脑启动IDEA一个后端服务要2min!谁忍的了?

一、背景 本人电脑性能一般&#xff0c;但是拥有着一台高性能的VDI&#xff08;虚拟桌面基础架构&#xff09;&#xff0c;以下是具体的配置 二、问题描述 但是&#xff0c;即便是拥有这么高的性能&#xff0c;每次运行基于Dubbo微服务架构下的微服务都贼久&#xff0c;以下…...

2022年山东省中职组“网络安全”赛项比赛任务书正式赛题

2022年山东省中职组“网络安全”赛项 比赛任务书 一、竞赛时间 总计&#xff1a;360分钟 竞赛阶段竞赛阶段 任务阶段 竞赛任务 竞赛时间 分值 A模块 A-1 登录安全加固 180分钟 200分 A-2 Nginx安全策略 A-3 日志监控 A-4 中间件服务加固 A-5 本地安全策略…...

RibbitMQ 入门到应用 ( 二 ) 安装

3.安装基本操作 3.1.下载安装 3.1.1.官网 下载地址 https://rabbitmq.com/download.html 与Erlang语言对应版本 https://rabbitmq.com/which-erlang.html 3.1.2.安装 Erlang 在确定了RabbitMQ版本号后&#xff0c;先下载安装Erlang环境 Erlang下载链接 https://packa…...

提取DataFrame中每一行的DataFrame.itertuples()方法

【小白从小学Python、C、Java】【计算机等级考试500强双证书】【Python-数据分析】提取DataFrame中的每一行DataFrame.itertuples()选择题关于以下python代码说法错误的一项是?import pandas as pddf pd.DataFrame({A:[a1,a2],B:[b1,b2]},index[i1,i2])print("【显示】d…...

基于卷积神经网络的立体视频编码质量增强方法_余伟杰

基于卷积神经网络的立体视频编码质量增强方法_余伟杰提出的基于TSAN的合成视点质量增强方法全局信息提取流像素重组局部信息提取流多尺度空间注意力机制提出的基于RDEN的轻量级合成视点质量增强方法特征蒸馏注意力块轻量级多尺度空间注意力机制概念扭曲失真孔洞问题失真和伪影提…...

【2023unity游戏制作-mango的冒险】-3.基础动作和动画API实现

&#x1f468;‍&#x1f4bb;个人主页&#xff1a;元宇宙-秩沅 hallo 欢迎 点赞&#x1f44d; 收藏⭐ 留言&#x1f4dd; 加关注✅! 本文由 秩沅 原创 收录于专栏&#xff1a;unity游戏制作 ⭐mango的基础动作动画的添加⭐ 文章目录⭐mango的基础动作动画的添加⭐&#x1f…...

跨域的几种解决方案?

1-jsonp 【前端后端实现】jsonp: 利用 <script> 标签没有跨域限制的漏洞&#xff0c;网页可以得到从其他来源动态产生的 JSON 数据。JSONP请求一定需要对方的服务器做支持才可以。JSONP优点是简单兼容性好&#xff0c;可用于解决主流浏览器的跨域数据访问的问题。缺点是仅…...

2022年山东省职业院校技能大赛网络搭建与应用赛项正式赛题

2022年山东省职业院校技能大赛 网络搭建与应用赛项 第二部分 网络搭建与安全部署&服务器配置及应用 竞赛说明&#xff1a; 一、竞赛内容分布 竞赛共分二个模块&#xff0c;其中&#xff1a; 第一模块&#xff1a;网络搭建及安全部署项目 第二模块&#xff1a;服务…...

【JUC并发编程】ArrayBlockingQueue和LinkedBlockingQueue源码2分钟看完

文章目录1、BlockingQueue1&#xff09;接口方法2&#xff09;阻塞队列分类2、ArrayBlockingQueue1&#xff09;构造函数2&#xff09;put()入队3&#xff09;take()出队3、LinkedBlockingQueue1&#xff09;构造函数2&#xff09;put()入队3&#xff09;take()出队1、Blocking…...

GitHub个人资料自述与管理主题设置

目录 关于您的个人资料自述文件 先决条件 添加个人资料自述文件 删除个人资料自述文件 管理主题设置 补充&#xff1a;建立一个空白文件夹 关于您的个人资料自述文件 可以通过创建个人资料 README&#xff0c;在 GitHub.com 上与社区分享有关你自己的信息。 GitHub 在个…...

Express篇-连接mysql

创建数据库配置文件config/sqlconfig.jsconst sqlconfig {host: localhost, // 连接地址user: root, //用户名password: ****, //密码port: 3306 , //端口号database: mysql01_dbbooks //数据库名 } module.exports sqlconfig封装数据库管理工具 utils/mysqlUtils.…...

win10 安装rabbitMQ详细步骤

win10 安装rabbitMQ详细步骤 win10 安装rabbitMQ详细步骤win10 安装rabbitMQ详细步骤一、下载安装程序二、安装配置erlang三、安装rabbitMQ四、验证初始可以通过用户名&#xff1a;guest 密码guest来登录。报错&#xff1a;安装RabbitMQ出现Plugin configuration unchanged.问题…...

【成为架构师课程系列】一线架构师:6个经典困惑及其解法

目录 一线架构师:6个经典困惑及其解法 多阶段还是多视图&#xff1f; 内置最佳实践 架构方法论:3个阶段&#xff0c;一个贯穿 Pre-architecture阶段&#xff1a;ADMEMS矩阵方法 Conceptual Architecture阶段&#xff1a;重大需求塑造做概念架构 Refined Architecture…...

光耦合器的定义与概述

光耦合器或光电耦合器是一种电子元件&#xff0c;基本上充当具有不同电压电平的两个独立电路之间的接口。光耦合器是可在输入和输出源之间提供电气隔离的常用元件。它是一个 6 引脚器件&#xff0c;可以有任意数量的光电探测器。 在这里&#xff0c;光源发出的光束作为输入和输…...

谷粒商城--品牌管理详情

目录 1.简单上传测试 2.Aliyun Spring Boot OSS 3.模块mall-third-service 4.前端 5.数据校验 6.JSR303数据校验 7.分组校验功能 8.自定义校验功能 9.完善代码 1.简单上传测试 OSS是对象存储服务&#xff0c;有什么用呢&#xff1f;把图片存储到云服务器上能让所有人…...

stack、queue和priority_queue

目录 一、栈&#xff08;stack&#xff09; 1.stack的使用 2.容器适配器 3.stack的模拟实现 二、队列&#xff08;queue&#xff09; 1.queue的使用 2.queue的模拟实现 三、双端队列&#xff08;deque&#xff09; 1.vector&#xff0c;list的优缺点 2.认识deque 四…...

怎样做网站结构优化/seo关键词搜索优化

来源&#xff1a;http://www.php.cn/csharp-article-359736.html一、过滤器简介 1.1、理解什么是过滤器 1、过滤器&#xff08;Filters&#xff09;就是向请求处理管道中注入额外的逻辑。提供了一个简单而优雅的方式来实现横切关注点。 2、所谓的过滤器&#xff08;Filters&…...

做水果蔬菜生意网站/南昌seo快速排名

现在&#xff0c;有一行括号序列&#xff0c;请你检查这行括号是否配对。输入第一行输入一个数N(0输出每组输入数据的输出占一行&#xff0c;如果该字符串中所含的括号是配对的&#xff0c;则输出Yes,如果不配对则输出No样例输入3[(])(])([[]()])样例输出NoNoYes#include#inclu…...

寻求南宁网站建设人员/专业seo优化推广

怀旧是一种什么滋味 怀旧是一种什么滋味&#xff0c;好像有人在你心上攥了一下。 感谢这个时代将我们记录默默保存 感谢某技术博客平台竟然还能保存自己10年前的博客文章 早起的鸟儿有虫吃 今天需要在某网站下载个资料&#xff0c;如今是知识付费时代哪个网站不搞个VIP服务都…...

pc端网站/哪有学电脑培训班

1.1 什么是Spark 1.2 Spark内置模块 Spark Core&#xff1a;实现了Spark的基本功能&#xff0c;包含任务调度、内存管理、错误恢复、与存储系统交互等模块。Spark Core中还包含了对弹性分布式数据集(Resilient Distributed DataSet&#xff0c;简称RDD)的API定义。 Spark SQL&…...

网站模板的缺点/免费网页设计制作网站

ShareSDK&#xff1b; 友盟&#xff1b; 百度分享&#xff1b; //支付宝支付 1&#xff0c;seller id&#xff1a; 2&#xff0c;partner id: 3&#xff0c;加密文件(公钥、私钥) 4&#xff0c;下载SDK&#xff08;网页版、无线版--支付宝论坛&#xff09; 5&#xff0c;scheme…...

有用模板网在线制作免费网站/杭州seo搜索引擎优化公司

前言 千万级大表如何优化&#xff0c;这是一个很有技术含量的问题&#xff0c;通常我们的直觉思维都会跳转到拆分或者数据分区。除此之外&#xff0c;还有其他的思路和解决方案。根据本人多年的工作经验&#xff0c;做了如下总结。 方案 "千万级大表优化"这句话有…...