Spring

1、Spring框架中单例bean是线程安全的吗?

不是线程安全的。当多用户同时请求一个服务时,容器会给每个请求分配一个线程,这些线程会并发执行业务逻辑。如果处理逻辑中包含对单例状态的修改,比如修改单例的成员属性,就必须考虑线程同步问题。Spring框架本身并不对单例bean进行线程安全封装,线程安全和并发问题需要开发者自行处理。

通常在项目中使用的Spring bean是不可变状态(如Service类和DAO类),因此在某种程度上可以说Spring的单例bean是线程安全的。如果bean有多种状态(如ViewModel对象),就需要自行保证线程安全。最简单的解决办法是将单例bean的作用域由“singleton”变更为“prototype”。

2、什么是AOP?

AOP,即面向切面编程,在Spring中用于将那些与业务无关但对多个对象产生影响的公共行为和逻辑抽取出来,实现公共模块复用,降低耦合。常见的应用场景包括公共日志保存和事务处理。

3、你们项目中有没有使用AOP?

我们之前在后台管理系统中使用AOP来记录系统操作日志。主要思路是使用AOP的环绕通知和切点表达式,找到需要记录日志的方法,然后通过环绕通知的参数获取请求方法的参数,例如类信息、方法信息、注解、请求方式等,并将这些参数保存到数据库。

4、Spring中是事务是如何实现的?

Spring实现事务的本质是利用AOP完成的。它对方法前后进行拦截,在执行方法前开启事务,在执行完目标方法后根据执行情况提交或回滚事务。

5、Spring中事务失效的场景有哪些?

在项目中,我遇到过几种导致事务失效的场景:

  1. 如果方法内部捕获并处理了异常,没有将异常抛出,会导致事务失效。因此,处理异常后应该确保异常能够被抛出。

  2. 如果方法抛出检查型异常(checked exception),并且没有在@Transactional注解上配置rollbackFor属性为Exception,那么异常发生时事务可能不会回滚。

  3. 如果事务注解的方法不是公开(public)修饰的,也可能导致事务失效。

6、Spring中bean的生命周期?

1、实例化: 给Bean分配内存空间(对应JVM中的“加载”,这里只是分配了内存);

2、设置属性:进行Bean的注入和装配

3、初始化

执行各种通知

执行初始化的前置工作

进行初始化工作(使用注解 @PostConstruct 初始化 或者 使用(xml)init-method 初始化, 前者技术比后者技术先进~);

执行初始化的后置工作

4、使用bean

5、销毁bean

值得注意的是:实例化和初始化是两个完全不同的过程,前者只是给Bean分配内存空间,而后者则是将程序执行权从系统级别转到用户级别,执行用户添加的业务代码。

图解:

7、spring中的循环引用?

循环依赖发生在两个或两个以上的bean互相持有对方,形成闭环。Spring框架允许循环依赖存在,并通过三级缓存解决大部分循环依赖问题:

  1. 一级缓存:单例池,缓存已完成初始化的bean对象。

  2. 二级缓存:缓存尚未完成生命周期的早期bean对象。

  3. 三级缓存:缓存ObjectFactory,用于创建bean对象。

8、那具体解决流程清楚吗?

解决循环依赖的流程如下:

  1. 实例化A对象,并创建ObjectFactory存入三级缓存。

  2. A在初始化时需要B对象,开始B的创建逻辑。

  3. B实例化完成,也创建ObjectFactory存入三级缓存。

  4. B需要注入A,通过三级缓存获取ObjectFactory生成A对象,存入二级缓存。

  5. B通过二级缓存获得A对象后,B创建成功,存入一级缓存。

  6. A对象初始化时,由于B已创建完成,可以直接注入B,A创建成功存入一级缓存。

  7. 清除二级缓存中的临时对象A。

9、构造方法出现循环依赖怎么解决?

由于构造函数是bean生命周期中最先执行的,Spring框架无法解决构造方法的循环依赖问题。可以使用@Lazy懒加载注解,延迟bean的创建直到实际需要时。

10、Spring核心容器IOC的理解、原理与实现

IOC就是控制反转

原来的对象是由使用者来进行控制,有了spring之后,可以把整个对象交给spring容器来进行管理。在需要的地方进行依赖注入就行,使用注解@Autowired,populateBean完成属性值的注入。

spring IOC容器:是使用map的结构来存储,在spring中一般存在三级缓存,singletonObjects存放完整的bean对象,整个bean的生命周期,从创建、使用、销毁的过程全部都是由容器来管理。

使用IOC的好处:降低代码耦合度。

传统模式,使用new对象的方式,但是这样不可以实现多态,比如我创建一个person对象,里面有一个eat(Apple apple)方法,那么调用这个eat方法的类,需要传入苹果(Apple)对象,之后我的这个方法改成吃梨子了,这个方法又改成eat(Pear pear)了,调用eat方法的类,又需要把之前的苹果改成梨子,扩展性差。

于是出现了面向接口编程,我在eat方法里面传入水果(Fruit)接口,之后苹果,梨只需要实现接口即可,调用eat方法的类,想吃梨子就传入梨子,想吃苹果传入苹果即可。

面向接口编程,也是有缺点的,面向接口时,在调用处会有接口和实现类的耦合,比如一个接口Person多个实现类(Student,Teacher),那就要Person s = new Student(); Person s = new Teacher(),所以就用Spring IOC容器来管理。使用IOC,解决了接口和实现类的耦合,调用方统一面向接口,然后使用是通过依赖注入指明调用那个实现类,这样实现类使用Service定义bean的名称,跟接口就解耦了,调用直接用两种方式指定:

1.用Java的Resource直接指定

@Resource(name = "SysCaptchaService2")
private SysCaptchaService sysCaptchaService2;

2.Autowired配合Qualifier指定

@Autowired
@Qualifier("SysCaptchaService")
private SysCaptchaService sysCaptchaService;

IOC底层原理

IOC底层主要是使用xml解析+反射+工厂模式实现,通过源码分析总结如下:

首先容器的创建过程,用到工厂模式BeanFactor接口的实现类DefaultListableBeanFactory创建bean工厂,先bean工厂设置一些参数(比如前置处理BeanPostProcessor、Aware接口)

然后通过加载解析bean对象,xml配置或者注解@Autowired,也就是准备定义BeanDefinition对象,这里也是解析xml配置

接下来就是一些扩展点的处理,也是BeanFactoryPostProcessor的处理包括展占位符处理PlaceholderConfigurerSupport(BeanFactoryPostProcessor子类),处理${password}等。

再通过反射(xml配置获取到全类名,得到Class对象,调用newInstance就可创建对象,BeanDefinition对象实例化成具体的bean对象,也就是先实例化,然后在初始化bean对象,填充属性,调用aware子类的方法,调用BeanPostProcessor前置处理,调用init-method,调用BeanPostProcessor后置处理。

初始化完成后,开始获取完整bean对象,getBean(),使用完成后,如果要销毁就调用destroyMethod。

11、Spring的bean如何优先创建?
  • @Bean方法参数注入

    @Configuration
    public class MytestConfigure {
    ​@Beanpublic BeanA beanA(BeanB demoB){System.out.println("bean A init");return new BeanA();}@Beanpublic BeanB beanB(){System.out.println("bean B init");return new BeanB();}
    }
    上面的两个Bean加载到Spring容器时,Spring容器优先加载 BeanB
  • @DependsOn注解,会先加载依赖的bean实例化,来控制 bean 之间的实例顺序,需要注意的是 bean 的初始化方法调用顺序无法保证

    @DependsOn("rightDemo2")
    @Component
    public class RightDemo1 {private String name = "right demo 1";public RightDemo1() {System.out.println(name);}
    }
    @Component
    public class RightDemo2 {private String name = "right demo 2";public RightDemo2() {System.out.println(name);}
    }        
  • 通过Spring扩展器PostProcessor,实现 BeanFactoryPostProcessor 接口方式,来手动控制 bean 的加载顺序

    @Component
    public class ABeanFactoryPostProcessor implements BeanFactoryPostProcessor {@Overridepublic void postProcessBeanFactory(ConfigurableListableBeanFactory configurableListableBeanFactory) throws BeansException {A.initA();}
    }
  • 在类上使用@Order注解可以为整个类的所有 Bean 定义指定顺序。这对于需要按照特定顺序初始化 Bean 的场景非常有用。

    • @Order的注解源码解读
      @Retention(RetentionPolicy.RUNTIME)
      @Target({ElementType.TYPE, ElementType.METHOD, ElementType.FIELD})
      @Documented
      public @interface Order {
      ​/*** 默认是最低优先级,值越小优先级越高*/int value() default Ordered.LOWEST_PRECEDENCE;
      ​
      }
      注解可以作用在类(接口、枚举)、方法、字段声明(包括枚举常量);
      注解有一个int类型的参数,可以不传,默认是最低优先级;
      通过常量类的值我们可以推测参数值越小优先级越高;
    • 创建BlackPersion、YellowPersion类,这两个类都实现CommandLineRunner
      package com.yaomy.common.order;
      ​
      import org.springframework.boot.CommandLineRunner;
      import org.springframework.core.annotation.Order;
      import org.springframework.stereotype.Component;
      ​
      /*** @Description: Description* @ProjectName: spring-parent* @Version: 1.0*/
      @Component
      @Order(1)
      public class BlackPersion implements CommandLineRunner {@Overridepublic void run(String... args) throws Exception {System.out.println("----BlackPersion----");}
      }
      package com.yaomy.common.order;
      ​
      import org.springframework.boot.CommandLineRunner;
      import org.springframework.core.annotation.Order;
      import org.springframework.stereotype.Component;
      ​
      /*** @Description: Description* @ProjectName: spring-parent* @Version: 1.0*/
      @Component
      @Order(0)
      public class YellowPersion implements CommandLineRunner {@Overridepublic void run(String... args) throws Exception {System.out.println("----YellowPersion----");}
      }
      输出:
      ----YellowPersion----
      ----BlackPersion----
      我们可以通过调整@Order的值来调整类执行顺序的优先级,即执行的先后;当然也可以将@Order注解更换为Ordered接口,效果是一样的
12、Spring的常见注解?

Spring的常见注解包括:

  1. 声明Bean的注解:@Component@Service@Repository@Controller

  2. 依赖注入相关注解:@Autowired@Qualifier@Resource

  3. 设置作用域的注解:@Scope

  4. 配置相关注解:@Configuration@ComponentScan@Bean

  5. AOP相关注解:@Aspect@Before@After@Around@Pointcut

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

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

相关文章

MathGPT的原理介绍,在中小学数学教学的应用场景,以及代码样例实现

大家好,我是微学AI,今天给大家介绍一下MathGPT的原理介绍,在中小学数学教学的应用场景,以及代码样例实现。MathGPT的核心架构是一个精心设计的多层次系统,旨在有效处理复杂的数学问题。其主要组成部分包括 数学知识图谱…

【Linux】man 手册的使用指南

man 手册的使用指南 man手册中文版上传至资源(用心整理,感谢理解!) man手册官方下载链接:https://mirrors.edge.kernel.org/pub/linux/docs/man-pages/ man 手册页:https://linux.die.net/man/ Linux man…

机器学习分析scRNA-seq解析急性髓系白血病中的疾病和免疫过程

急性髓性白血病(AML,Acute myeloid leukemia)是一种存在于复杂微环境中的疾病。作者基于scRNA-seq分析了来自40例骨髓抽吸donor的38,410个细胞,包括16例AML患者和5例健康donor。然后,应用机器学习分类器来区分恶性细胞…

【缓存策略】你知道 Write Back(回写)这个缓存策略吗?

👉博主介绍: 博主从事应用安全和大数据领域,有8年研发经验,5年面试官经验,Java技术专家,WEB架构师,阿里云专家博主,华为云云享专家,51CTO 专家博主 ⛪️ 个人社区&#x…

1小时构建Vue3知识体系-Vue的响应式,让数据动起来

本文转载自:https://fangcaicoding.cn/course/12/62 大家好!我是方才,目前是8人后端研发团队的负责人,拥有6年后端经验&3年团队管理经验。 系统学习践行者!近期在系统化输出前端入门相关技术文章,期望能…

Docker网络详解

安装Docker时,它会自动创建三个网络,bridge(创建容器默认连接到此网络)、 none 、host 网络模式简介Host容器将不会虚拟出自己的网卡,配置自己的IP等,而是使用宿主机的IP和端口。Bridge此模式会为每一个容…

宝塔面板部署前端项目(包含ssl证书部署)

环境: ①nginx(这里使用的版本为1.21.41) ②前端项目文件(以根目录打包的文件) ③域名 ④SLL数字证书的key文件和.pem文件(我们这里用的是nginx部署,因此下载证书的时候,下载nginx对…

【区别】ONLYOFFICE心得体会,8.2与8.1区别

本站以分享各种运维经验和运维所需要的技能为主 《python零基础入门》:python零基础入门学习 《python运维脚本》: python运维脚本实践 《shell》:shell学习 《terraform》持续更新中:terraform_Aws学习零基础入门到最佳实战 《k8…

Equity-Transformer:求解NP-Hard Min-Max路由问题的顺序生成算法(AAAI-24)(未完)

文章目录 AbstractIntroduction问题表述MethodologyAbstract 最小最大路由问题旨在通过智能体合作完成任务来最小化多个智能体中最长行程的长度。这些问题包括对现实世界有重大影响的应用场景,但已知属于NP-hard问题。现有方法在大规模问题上面临挑战,尤其是在需要协调大量智…

ScrumMaster认证机构及CSM、PSM、RSM价值解析

近十年Scrum在国内备受关注,成为一种最流行的现代敏捷工作方式。ScrumMaster这一独特的角色,在企业内部推动Scrum落地的过程中越来越重要。各种ScrumMaster认证课程也蜂拥而至,甚至鱼目混珠。 我们为大家梳理了目前市面上出现的ScrumMaster认…

HLS实现图像二值化

最近在学习HLS语言,所以就自己摸索尝试了用HLS实现了图像二值化,把这个内容总结一下,分享出来。 首先打开HLS,然后新建一个Project,之后再在Source栏点击右键,选择New File...,创建名为pixelBi…

[ 内网渗透实战篇-1 ] 单域环境搭建与安装域环境判断域控定位CS插件装载CS上线

🍬 博主介绍 👨‍🎓 博主介绍:大家好,我是 _PowerShell ,很高兴认识大家~ ✨主攻领域:【渗透领域】【数据通信】 【通讯安全】 【web安全】【面试分析】 🎉点赞➕评论➕收藏 养成习…

通过物流分拣系统来理解RabbitMQ的消息机制

RabbitMQ作为一个消息中间件,通过队列和路由机制,帮助应用程序高效传递消息。而它的消息流转过程,其实可以用物流分拣系统来直观理解。 在一个典型的物流分拣系统中,包裹会经过多个节点(比如分拣中心、配送站&#xf…

别再乱搜了 这 5个宝藏AE模板网站,小白也能做出大片级动画

Hello,大家好,我是后期圈! 今天来聊聊一个后期人都绕不开的话题:AE模板网站!模板可是后期人的福音,无论你是想要惊艳的开场动画,酷炫的转场效果,还是个性化的文字特效,一…

CSS 编写位置详解及优先级分析

在前端开发中,CSS 的编写位置对项目的组织结构和维护性至关重要。不同的编写位置不仅影响代码的可读性和复用性,还决定了样式应用的优先级。 本文将根据编写位置的不同,详细介绍其定义、使用场景和优先级。 行内样式(Inline Styles) 行内样式(又称:内联样式)是将 CS…

ChatGPT 搜索 vs Google 搜索

原文:Amanda Caswell - 2024.11.01 随着 OpenAI 推出的实时搜索功能,ChatGPT 正在逐步成为像 Google 这样的传统搜索引擎的竞争对手。ChatGPT 以其对话式的回答方式而闻名,它能够在没有广告干扰的情况下提供实时的上下文信息。 我迫不及待地…

多进程的操作和案例

文章目录 高效编程一、多任务原理二、进程1、概念2、使用进程3、全局变量在多个子进程中不能共享4、启动大量子进程5、map方法6、单进程与多进程复制文件对比7、进程间通信8、进程实现生产者消费者9、案例(抓取斗图) 高效编程 一、多任务原理 概念 现代…

【更新中】《硬件架构的艺术》笔记(二):时钟与复位

本章主要针对ASIC设计给出建议,独立于CAD工具以及工艺,主要针对模块设计和存储器接口。 同步设计 这是对时钟域控制最安全的方法,单个主时钟和单个主置位/复位信号驱动设计中所有时序器件。 避免使用行波计数器 行波计数器:用…

Spring Boot编程训练系统:架构设计与技术选型

3系统分析 3.1可行性分析 通过对本编程训练系统实行的目的初步调查和分析,提出可行性方案并对其一一进行论证。我们在这里主要从技术可行性、经济可行性、操作可行性等方面进行分析。 3.1.1技术可行性 本编程训练系统采用SSM框架,JAVA作为开发语言&#…

DAY111PHP开发框架THIKNPHP反序列化POP利用链RCE执行文件删除

一、文件删除利用链分析 1、__destruct发现调用$this->removeFiles(); 2、removeFiles();函数方法file_exists,unlink($filename);文件删除功能 3、unserialize(base64_decode($_GET[id])); 有可控变量 4、pop文件删除利用链的使用 只有在这个类中调用 Files可…