分享下我整理的Spring框架八股笔记

1.Spring

-1.Spring用到了哪些设计模式

Spring框架在其设计和实现中使用了多种设计模式,这些设计模式有助于提高代码的可重用性、灵活性和可维护性。以下是一些在Spring中常用的设计模式:

  1. 工厂模式:Spring通过BeanFactory和ApplicationContext来创建对象,其中BeanFactory就是简单工厂模式的体现。工厂模式隐藏了对象实例化的复杂性,并提供一个统一的方式来获取对象。
  2. 单例模式:在Spring中,默认情况下,bean以单例的形式存在。这意味着对于每个bean定义,Spring容器只会创建一个共享的实例。这样做可以减少系统资源的消耗,并减少垃圾回收器的压力。
  3. 代理模式:Spring的面向切面编程(AOP)功能使用到了JDK的动态代理和CGLIB字节码生成技术。这使得可以在不修改源代码的情况下,为对象添加额外的行为。
  4. 策略模式:例如,Resource接口的不同实现类针对不同的资源文件实现了不同的资源获取策略。策略模式允许在运行时选择算法或操作的具体实现。
  5. 模板方法模式:Spring中的JdbcTemplate、RestTemplate等都是模板方法模式的应用。它们提供了一个操作的框架,而具体的实现步骤则可以由子类来提供,从而实现代码复用和减少重复代码。
  6. 观察者模式:Spring事件驱动模型使用了观察者模式。当某个事件发生时,所有注册为该事件监听者的bean都会收到通知。
  7. 装饰器模式:在Spring中,装饰器模式用于给对象添加额外的功能,这比生成子类更为灵活。
  8. 适配器模式:在Spring MVC中,处理器适配器将不同的控制器适配成统一的Handler接口,使得不同的控制器可以被统一处理。
  9. 责任链模式:在AOP中,责任链模式用于组织多个拦截器,形成一个处理请求的责任链。
  10. 桥接模式:在Spring中,桥接模式可以用来解耦抽象部分和实现部分,例如动态切换不同的数据源。

综上所述,这些设计模式的使用不仅体现了Spring框架的灵活性和扩展性,也使得开发人员能够更加专注于业务逻辑,而不必关心底层的细节实现。

0.Spring的优点/为什么用Spring框架

Spring 是一款开源的轻量级的控制反转(IoC)和面向切面(AOP) 开发框架,可以提高开发人员的开发效率以及系统的可维护性。

1.通过Ioc控制反转和DI依赖注入实现松耦合,能够降低组件之间的耦合度,使得代码更加灵活、易于维护和扩展(Spring就是一个大工厂,可以将所有对象的创建和依赖关系维护都交给spring管理)

2.支持AOP面向切面的编程,把日志、事务管理等从业务逻辑中分离出来,提高了代码的复用性和可维护性。

3.支持声明式事务,可以通过声明式事务来管理数据库操作的事务

4.Spring是非侵入式的。使用Spring的框架不用继承Spring的类和接口,

5.Spring框架拥有庞大的社区支持,提供了丰富的文档、教程等资料,用的人多大家交流问题也更加方便

1.IOC和DI

1.什么是IOC控制反转呢?

IOC-Inversion of Control,即控制反转。IoC(Inversion of Control:控制反转) 是一种设计思想,而不是一个具体的技术实现。IoC 的思想就是将原本在程序中手动创建对象的控制权,交由 外部来管理。

为什么叫控制反转?

  • 控制:指的是对象创建(实例化、管理)的权力
  • 反转:控制权交给外部环境(Spring 框架、IoC 容器)

2.DI依赖注入

(1)什么是依赖注入呢?

在Spring创建对象的过程中,把对象依赖的属性注入到对象中。spring就是通过反射来实现注入的。依赖注入主要有三种方式:注解注入(@Autowired),构造器注入和属性注入

3.IOC和DI的作用

最终目标就是:充分解耦,具体实现靠:

  • 使用IOC容器管理bean(IOC)
  • 在IOC容器内将有依赖关系的bean进行关系绑定(DI)
  • 最终:使用对象时不仅可以直接从IOC容器中获取,并且获取到的bean已经绑定了所有的依赖关系.

4.Spring的IOC和DI用了什么设计模式

Spring 的 IoC(控制反转)和 DI(依赖注入)使用了工厂模式、单例模式和代理模式等设计模式。具体如下:

  1. 工厂模式:IoC 容器负责创建对象,当需要创建一个对象时,只需配置好相应的配置文件或注解,无需关心对象的创建过程。IoC 容器就像一个工厂,它根据配置文件或注解来生成和管理对象实例。
  2. 单例模式:在 Spring 框架中,默认情况下,Bean 是单例的,即在整个应用中只有一个实例。这是通过单例模式实现的,确保每个 Bean 的生命周期内只有一个共享的实例。
  3. 代理模式:AOP(面向切面编程)是 Spring 的另一个核心特性,它使用代理模式来实现。通过代理模式,可以在不修改原始类代码的情况下,为对象提供额外的功能,例如事务管理和日志记录。

综上所述,这些设计模式共同工作,使得 Spring 框架能够提供一个高度解耦、易于扩展和维护的应用程序架构。

2.AOP

1.什么是AOP

AOP是面向切面编程,将公共逻辑(事务管理、日志、缓存等)封装成切面,跟业务代码进行分离,抽取公共模块复用,降低耦合。切面就是那些与业务无关,但所有业务模块都会调用的公共逻辑。

具体组成:

1.连接点(JoinPoint):程序执行过程中的任意位置,粒度为执行方法、抛出异常、设置变量等

  • 在SpringAOP中,理解为方法的执行

2.切入点(Pointcut):匹配连接点的式子

  • 在SpringAOP中,一个切入点可以描述一个具体方法,也可也匹配多个方法
  • 连接点范围要比切入点范围大,是切入点的方法也一定是连接点,但是是连接点的方法就不一定要被增强,所以可能不是切入点。
  • 切入点定义依托一个不具有实际意义的方法进行,即无参数、无返回值、方法体无实际逻辑,然后在上面加个@PointCut注解。

3.通知(Advice):在切入点处执行的操作,也就是共性功能,是通知类的一个函数

4.通知类:定义通知的类

5.切面(Aspect):描述通知与切入点的对应关系。

2.AOP怎么实现

AOP有两种实现方式:静态代理和动态代理。

静态代理

静态代理:代理类在编译阶段生成,在编译阶段将通知织入Java字节码中,也称编译时增强。AspectJ使用的是静态代理。

缺点:代理对象需要与目标对象实现一样的接口,并且实现接口的方法,会有冗余代码。同时,一旦接口增加方法,目标对象与代理对象都要维护。

动态代理

动态代理:代理类在程序运行时创建,AOP框架不会去修改字节码,而是在内存中临时生成一个代理对象,在运行期间对业务方法进行增强,不会生成新类。

3.Spring的AOP是怎么实现的

SpringAOP是通过动态代理实现的。而SpringAOP使用了两种动态代理,分别是JDK的动态代理,以及CGLib的动态代理

如果要代理的对象,实现了某个接口,那么 Spring AOP 会使用 JDK 动态代理,去创建代理对象,而对于没有实现接口的对象,就无法使用 JDK Proxy 去进行代理了,这时候 Spring AOP 会使用 Cglib动态代理 生成一个被代理对象的子类来作为代理。

4.JDK动态代理和CGLIB动态代理的区别

JDK动态代理

如果目标类实现了接口,Spring AOP会选择使用JDK动态代理目标类。代理类根据目标类实现的接口动态生成,不需要自己编写,生成的动态代理类和目标类都实现相同的接口。JDK动态代理的核心是InvocationHandler接口和Proxy类。

缺点:目标类必须有实现的接口。如果某个类没有实现接口,那么这个类就不能用JDK动态代理。

CGLIB动态代理

通过继承实现。如果目标类没有实现接口,那么Spring AOP会选择使用CGLIB来动态代理目标类。CGLIB(Code Generation Library)可以在运行时动态生成类的字节码,动态创建目标类的子类对象,在子类对象中增强目标类。

优点:目标类不需要实现特定的接口,更加灵活。

缺点:CGLIB是通过继承的方式做的动态代理,因此如果某个类被标记为final,那么它是无法使用CGLIB做动态代理的。

5.Spring AOP的相关术语

  • 连接点(JoinPoint):程序执行过程中的任意位置,粒度为执行方法、抛出异常、设置变量等在SpringAOP中,理解为方法的执行
  • 切入点(Pointcut):匹配连接点的式子在SpringAOP中,一个切入点可以描述一个具体方法,也可也匹配多个方法一个具体的方法:如com.itheima.dao包下的BookDao接口中的无形参无返回值的save方法匹配多个方法:所有的save方法,所有的get开头的方法,所有以Dao结尾的接口中的任意方法,所有带有一个参数的方法连接点范围要比切入点范围大,是切入点的方法也一定是连接点,但是是连接点的方法就不一定要被增强,所以可能不是切入点。
  • 通知(Advice):在切入点处执行的操作,也就是共性功能在SpringAOP中,功能最终以方法的形式呈现
  • 通知类:定义通知的类
  • 切面(Aspect):描述通知与切入点的对应关系。

Spring通知类型

Spring切面可以应用5种类型的通知:

  1. 前置通知(Before):在目标方法被调用之前调用通知功能;
  2. 后置通知(After):在目标方法完成之后调用通知,此时不会关心方法的输出是什么;
  3. 返回通知(After-returning ):在目标方法成功执行之后调用通知;
  4. 异常通知(After-throwing):在目标方法抛出异常后调用通知;
  5. 环绕通知(Around):通知包裹了被通知的方法,在被通知的方法调用之前和调用之后执行自定义的逻辑。

6.Spring一般是怎么使用AOP(公共日志保存/事务处理)

1.怎么用AOP实现公共日志保存

使用aop中的环绕通知+切点表达式,这个表达式就是要找到要记录日志的方法,然后通过环绕通知的参数获取请求方法的参数,比如类信息、方法信息、注解、请求方式等,获取到这些参数以后,保存到ES数据库

2.怎么用AOP实现事务处理

在方法前后进行拦截,在执行方法之前开启事务,在执行完目标方法之后根据执行情况提交或者回滚事务。

7.多个切面的执行顺序如何控制?

可以使用@Order 注解直接定义切面顺序

// 值越小优先级越高
@Order
@Component
@Aspect
public class LoggingAspect implements Ordered {

3.Spring事务

1.什么是事务

事务是逻辑上的一组操作,要么都执行,要么都不执行。

2.事务的特性ACID

原子性Atomicity):事务是最小的执行单位,不允许分割。事务的原子性确保动作要么全部完成,要么完全不起作用;

一致性Consistency):执行事务前后,数据保持一致,例如转账业务中,无论事务是否成功,转账者和收款人的总额应该是不变的;

隔离性Isolation):并发访问数据库时,一个用户的事务不被其他事务所干扰,各并发事务之间数据库是独立的;

持久性Durability):一个事务被提交之后。它对数据库中数据的改变是持久的,即使数据库发生故障也不应该对其有任何影响。

3.Spring事务实现方式(声明式和编程式)

Spring事务机制主要包括声明式事务和编程式事务。

  • 编程式事务:通过编程的方式管理事务,这种方式带来了很大的灵活性,但很难维护。
  • 声明式事务:在 XML 配置文件中配置或者直接基于注解(推荐使用) : 实际是通过 AOP 实现(基于@Transactional 的全注解方式使用最多)

4.Spring事务有几种事务传播行为

事务传播行为是为了解决业务层方法之间互相调用的事务问题

当事务方法被另一个事务方法调用时,必须指定事务应该如何传播。例如:方法可能继续在现有事务中运行,也可能开启一个新事务,并在自己的事务中运行。

在TransactionDefinition接口中定义了七个事务传播行为:

PROPAGATION_NESTED 与PROPAGATION_REQUIRES_NEW的区别:

使用PROPAGATION_REQUIRES_NEW时,内层事务与外层事务是两个独立的事务。一旦内层事务进行了提交后,外层事务不能对其进行回滚。两个事务互不影响。

使用PROPAGATION_NESTED时,外层事务的回滚可以引起内层事务的回滚。而内层事务的异常并不会导致外层事务的回滚,它是一个真正的嵌套事务。

5.Spring事务隔离级别

Spring定义了一个枚举类:Isolation,里面有5个Spring事务隔离级别

1.ISOLATION_DEFAULT :使用后端数据库默认的隔离级别,MySQL 默认采用的 REPEATABLE_READ 隔离级别 Oracle 默认采用的 READ_COMMITTED 隔离级别.

2.读未提交ISOLATION_READ_UNCOMMITTED` :最低的隔离级别,使用这个隔离级别很少,因为它允许读取尚未提交的数据变更,可能会导致脏读、幻读或不可重复读

3.读已提交ISOLATION_READ_COMMITTED`: 允许读取并发事务已经提交的数据,可以阻止脏读,但是幻读或不可重复读仍有可能发生

4.可重复读ISOLATION_REPEATABLE_READ: 对同一字段的多次读取结果都是一致的,除非数据是被本身事务自己所修改,可以阻止脏读和不可重复读,但幻读仍有可能发生。

5.可串行化ISOLATION_SERIALIZABLE` : 最高的隔离级别,完全服从 ACID 的隔离级别。所有的事务依次逐个执行,这样事务之间就完全不可能产生干扰,也就是说,该级别可以防止脏读、不可重复读以及幻读。但是这将严重影响程序的性能。通常情况下也不会用到该级别。

6.Spring事务失效场景

1.访问权限问题:如果事务方法的访问权限不是定义成public,这样会导致事务失效,因为spring要求被代理方法必须是public的。

2. 方法用final修饰:如果事务方法用final修饰,将会导致事务失效。因为spring事务底层使用了aop,也就是通过jdk动态代理或者cglib,帮我们生成了代理类,在代理类中实现的事务功能。但如果某个方法用final修饰了,那么在它的代理类中,就无法重写该方法添加事务功能。

3.对象没有被spring管理:使用spring事务的前提是:对象要被spring管理,需要创建bean实例。如果类没有加@Controller、@Service、@Component、@Repository等注解,即该类没有交给spring去管理,那么它的方法也不会生成事务。

4.在代码中捕获异常没有抛出:事务通知只有捉到了目标抛出的异常才能进行后续的回滚处理。如果我们自己捕获了异常处理掉了没有抛出,这种情况下spring事务不会回滚。

5.表不支持事务:如果MySQL使用的存储引擎是myisam,这样的话是不支持事务的。因为myisam存储引擎不支持事务。

7.@Transactional注解,注解在什么时候会失效

@Transactional注解在以下情况下会失效:

  1. 方法内部调用了同类中的另一个非事务方法。因为Spring的事务管理是基于AOP代理实现的,当一个类中的方法调用另一个方法时,实际上是通过代理对象进行调用的。如果被调用的方法没有使用@Transactional注解,那么事务管理将不会生效。
  2. 异常类型不正确。@Transactional注解默认只对RuntimeException类型的异常进行回滚,如果是其他类型的异常,需要指定rollbackFor属性。例如,如果要对Exception类型的异常进行回滚,可以这样写:@Transactional(rollbackFor = Exception.class)。
  3. 数据库引擎不支持事务。如果使用的数据库引擎不支持事务,那么@Transactional注解将无法生效。例如,MySQL的MyISAM存储引擎就不支持事务。
  4. 多数据源配置错误。在使用多数据源的情况下,如果不同数据源之间的事务管理没有正确配置,那么@Transactional注解可能会失效。需要确保每个数据源都有对应的事务管理器和事务通知器。
  5. 事务传播行为设置不当。@Transactional注解有一个propagation属性,用于设置事务的传播行为。如果不正确地设置了传播行为,可能会导致事务失效。例如,如果设置为Propagation.REQUIRES_NEW,那么每次调用都会创建一个新的事务,而不是加入到当前事务中。

4.bean

0.Sping 的bean为什么用到了单例模式?

Spring中的Bean默认使用单例模式,以下是几个可能的原因:

  • 节省资源:单例模式确保一个类只有一个实例,这样可以减少系统资源的消耗,特别是当一个对象的创建和销毁需要较大成本时,如数据库连接或大型配置对象。
  • 共享状态:单例模式允许多个对象共享一个实例的状态,这在需要共享数据或维持特定状态的场景中非常有用。
  • 性能提升:由于不需要频繁地创建和销毁对象,单例模式可以提高应用程序的性能。
  • 容器管理:Spring容器负责管理单例Bean的生命周期,包括创建、初始化、装配和其他生命周期回调,这有助于简化Bean的管理和维护。

综上所述,Spring中的Bean使用单例模式主要是为了节省资源、共享状态、提高性能以及方便容器管理。这些因素共同作用,使得单例模式成为Spring Bean的默认选择。当然,如果需要,开发者也可以将Bean定义为原型模式,以便每次请求都创建一个新的实例。

1.什么是bean

Bean 代指的就是那些被 IoC 容器所管理的对象。

我们需要告诉 IoC 容器帮助我们管理哪些对象,这个是通过配置元数据来定义的。配置元数据可以是 XML 文件、注解或者 Java 配置类。

2.将一个类声明为 Bean 的注解有哪些?

  • @Component:通用的注解,可标注任意类为 Spring 组件。如果一个 Bean 不知道属于哪个层,可以使用@Component 注解标注。
  • @Repository : 对应持久层即 Dao 层,主要用于数据库相关操作。
  • @Service : 对应服务层,主要涉及一些复杂的逻辑,需要用到 Dao 层。
  • @Controller : 对应 Spring MVC 控制层,主要用于接受用户请求并调用 Service 层返回数据给前端页面。

3.@Component 和 @Bean 的区别是什么?

都是使用注解定义 Bean。@Bean 是使用 Java 代码装配 Bean,@Component 是自动装配 Bean。

@Component 注解用在类上,表明一个类会作为组件类,并告知Spring要为这个类创建bean,每个类对应一个 Bean。

@Bean 注解用在方法上,表示这个方法会返回一个 Bean。@Bean 需要在配置类中使用,即类上需要加上@Configuration注解。

当我们引用第三方库中的类需要装配到 Spring容器时,则只能通过 @Bean来实现。

4.Bean 的作用域/作用范围有哪些?

Spring 中 Bean 的作用域通常有下面几种:

  • singleton : IoC 容器中只有唯一的 bean 实例。Spring 中的 bean 默认都是单例的,是对单例设计模式的应用。
  • prototype : 每次获取都会创建一个新的 bean 实例。也就是说,连续 getBean() 两次,得到的是不同的 Bean 实例。
  • request (仅 Web 应用可用): 每一次 HTTP 请求都会产生一个新的 bean(请求 bean),该 bean 仅在当前 HTTP request 内有效。
  • session (仅 Web 应用可用) : 每一次来自新 session 的 HTTP 请求都会产生一个新的 bean(会话 bean),该 bean 仅在当前 HTTP session 内有效。
  • application/global-session (仅 Web 应用可用):每个 Web 应用在启动时创建一个 Bean(应用 Bean),该 bean 仅在当前应用启动时间内有效。
  • websocket (仅 Web 应用可用):每一次 WebSocket 会话产生一个新的 bean。

5.bean是线程安全的吗

Spring 框架中的 Bean 是否线程安全,取决于其作用域和状态。

prototype 作用域下,每次获取都会创建一个新的 bean 实例,不存在资源竞争问题,所以不存在线程安全问题。singleton 作用域下,IoC 容器中只有唯一的 bean 实例,可能会存在资源竞争问题,这取决于 Bean 是否有状态(就是说这个bean是否是包含可变的成员变量的对象)。如果这个 bean 是有状态的话,那就存在线程安全问题(**有状态 Bean 是指)。

不过,大部分 Bean 实际都是无状态(没有定义可变的成员变量)的(比如 Dao、Service),这种情况下, Bean 是线程安全的。

单例bean线程安全问题解决办法

对于有状态单例 Bean 的线程安全问题,常见的有两种解决办法:

  1. 在 Bean 中尽量避免定义可变的成员变量。
  2. 在类中定义一个 ThreadLocal 成员变量,将需要的可变成员变量保存在 ThreadLocal 中(推荐的一种方式)。

5.SpringBoot如何实现自动装配?

SpringBoot通过**@EnableAutoConfiguration注解和自动配置类**实现自动装配。

SpringBoot的自动装配机制主要涉及以下几个步骤:

  1. 使用@SpringBootConfiguration注解:该注解中包含@EnableAutoConfiguration,它是实现自动装配的起始点。
  2. 启用自动配置:通过@EnableAutoConfiguration注解启用自动配置功能,该注解会导入一个特殊的组件,即AutoConfigurationImportSelector类型的组件。
  3. 加载自动配置类:AutoConfigurationImportSelector类型的组件会根据项目的依赖以及spring.factories文件中的配置,自动导入相应的自动配置类到Spring容器中。
  4. 按需加载配置类:所有被扫描到的自动配置类将根据条件进行生效,比如对应的配置文件是否存在,依赖是否满足等。满足条件的自动配置类将会为容器装配所需的组件。
  5. 自定义配置:如果需要替换或修改默认的自动配置,可以通过定义自己的@Bean来替换默认的Bean,或者在application.properties中修改相关参数来达到定制化配置的目的。
  6. SPI机制:SpringBoot还采用了Service Provider Interface (SPI)机制来实现一些自动装配的功能,使得程序可以自动地、可插拔地进行装配。

综上所述,SpringBoot的自动装配大大简化了项目的配置工作,允许开发者更专注于业务代码的编写,而无需过多关心底层的配置细节。不过,理解其背后的原理有助于更好地掌控SpringBoot应用的配置和开发。

6.bean自动装配的方式/注入方式有哪些?

Spring的自动装配有三种模式:byType(根据类型),byName(根据名称)、constructor(根据构造函数)。

byType

找到与依赖类型相同的bean注入到另外的bean中,这个过程需要借助setter注入来完成,因此必须存在set方法,否则注入失败。

默认情况下@Autowired是按类型匹配的(byType)。如果需要按名称(byName)匹配的话,可以使用@Qualifier注解与@Autowired结合。

当需要创建多个相同类型的 bean 并希望仅使用属性装配其中一个 bean 时,可以使用@Qualifier 注解和 @Autowired 通过指定应该装配哪个 bean 来消除歧义。

byName

将属性名与bean名称进行匹配,如果找到则注入依赖bean。

constructor

无论名称是否匹配,存在单个实例则优先按类型进行参数匹配,当存在多个类型相同实例时,按名称优先匹配,如果没有找到对应名称,则注入失败。

7.bean的生命周期

1.调用bean的构造方法创建Bean

2.通过反射调用setter方法进行属性的依赖注入

3.如果Bean实现了BeanNameAware接口,Spring将调用setBeanName(),设置 Bean的name(xml文件中bean标签的id)

4.如果Bean实现了BeanFactoryAware接口,Spring将调用setBeanFactory()把bean factory设置给Bean

5.如果存在BeanPostProcessor,Spring将调用它们的postProcessBeforeInitialization(预初始化)方法,在Bean初始化前对其进行处理

6.如果Bean实现了InitializingBean接口,Spring将调用它的afterPropertiesSet方法,然后调用xml定义的 init-method 方法,两个方法作用类似,都是在初始化 bean 的时候执行

7.如果存在BeanPostProcessor,Spring将调用它们的postProcessAfterInitialization(后初始化)方法,在Bean初始化后对其进行处理

8.Bean初始化完成,供应用使用,这里分两种情况:

8.1 如果Bean为单例的话,那么容器会返回Bean给用户,并存入缓存池。如果Bean实现了DisposableBean接口,Spring将调用它的destory方法,然后调用在xml中定义的 destory-method方法,这两个方法作用类似,都是在Bean实例销毁前执行。

8.2 如果Bean是多例的话,容器将Bean返回给用户,剩下的生命周期由用户控制。

8.BeanFactory和FactoryBean的区别?

BeanFactory:是所有Spring Bean的容器根接口,给Spring 的容器定义一套规范,给IOC容器提供了一套完整的规范,比如我们常用到的getBean方法等

FactoryBean:是一个bean。但是他不是一个普通的bean,是可以创建对象的bean。。通常是用来创建比较复杂的bean,一般的bean 直接用xml配置即可,但如果一个bean的创建过程中涉及到很多其他的bean 和复杂的逻辑,直接用xml配置比较麻烦,这时可以考虑用FactoryBean,可以隐藏实例化复杂Bean的具体的细节.

9.BeanFactory和ApplicationContext有什么区别?

BeanFactory和ApplicationContext是Spring的两大核心接口,都可以当做Spring的容器。其中ApplicationContext是BeanFactory的子接口。

两者区别如下:

1、功能上的区别。BeanFactory是Spring里面最底层的接口,包含了各种Bean的定义,读取bean配置文档,管理bean的加载、实例化,控制bean的生命周期,维护bean之间的依赖关系。

ApplicationContext接口作为BeanFactory的派生,除了提供BeanFactory所具有的功能外,还提供了更完整的框架功能,如继承MessageSource、支持国际化、统一的资源文件访问方式、同时加载多个配置文件等功能。

2、加载方式的区别。BeanFactroy采用的是延迟加载形式来注入Bean的,即只有在使用到某个Bean时(调用getBean()),才对该Bean进行加载实例化。这样,我们就不能发现一些存在的Spring的配置问题。如果Bean的某一个属性没有注入,BeanFacotry加载后,直至第一次使用调用getBean方法才会抛出异常。

而ApplicationContext是在容器启动时,一次性创建了所有的Bean。这样,在容器启动时,我们就可以发现Spring中存在的配置错误,这样有利于检查所依赖属性是否注入。 ApplicationContext启动后预载入所有的单例Bean,那么在需要的时候,不需要等待创建bean,因为它们已经创建好了。

相对于基本的BeanFactory,ApplicationContext 唯一的不足是占用内存空间。当应用程序配置Bean较多时,程序启动较慢。

10.怎么让2个bean按顺序加载?

当一个 bean 需要在另一个 bean 初始化之后再初始化时,可以使用@DependOn注解

11.spring的bean是否会被jvm的gc回收

Spring的单例(singleton)bean在Spring容器运行期间通常不会被JVM的垃圾回收器(GC)回收,而原型(prototype)bean则可能在不再被引用时被回收。具体如下:

  1. 单例(Singleton)Beans:默认情况下,Spring容器中创建的bean是单例的,即在整个应用程序生命周期内只存在一个实例。这些单例bean通常与Spring容器具有相同的生命周期,除非Spring容器被关闭或bean被显式销毁,否则它们会一直存在于内存中,因此不会被JVM的GC回收。
  2. 原型(Prototype)Beans:与单例bean不同,原型bean每次请求时都会创建一个新的实例。这意味着它们的生命周期通常较短,使用完毕后如果没有其他引用指向它们,就可能会被JVM的GC回收。
  3. 作用域和生命周期:Spring bean的作用域和生命周期也会影响其是否被回收。例如,如果一个bean被配置为在某个特定的生命周期结束或某个条件满足时销毁,那么它将可能被JVM回收。
  4. 弱引用和软引用:如果在Spring配置中使用了弱引用或软引用,那么即使bean仍然在Spring容器中,也可能在JVM的下一次GC周期中被回收,因为弱引用和软引用的对象更容易被GC处理。
  5. Spring容器关闭:当Spring容器关闭时,所有的单例bean都会被销毁,此时它们将变得不可达,从而可能被JVM的GC回收。

综上所述,Spring的bean是否会被JVM的GC回收取决于其作用域、生命周期以及Spring容器的状态。单例bean在Spring容器运行期间通常不会被回收,而原型bean和其他特定条件下的bean可能会被回收。

12.springboot中不想加载一个bean如何做

要在Spring Boot中阻止一个bean被加载,您可以采取以下几种方法:

  1. 自定义@ComponentScan:通过自定义@ComponentScan注解,您可以指定需要扫描的包路径,从而排除不想加载的bean。在@ComponentScan注解中使用excludeFilters属性来排除特定的类。
  2. 使用@SpringBootApplication的exc:如果您使用的是@SpringBootApplication注解,可以利用它的exclude属性来排除自动配置类。例如,如果您不想加载某个自动配置类,可以在@SpringBootApplication注解中列出这个类。

剩余60%内容,订阅专栏后可继续查看/也可单篇购买

Java抽象带蓝子的笔记专栏 文章被收录于专栏

我的笔记专栏,内有自己整理的八股知识笔记和算法刷题笔记,我会不断通过他人和自己的面经来更新和完善自己的八股笔记。专栏每增加一篇文章费用就会上涨一点,如果你喜欢的话建议你尽早订阅。内有超详细苍穹外卖话术!后续还会更新其他项目和我的实习经历的话术!敬请期待!

全部评论
终于等到spring了篮子哥,就好这一口看别的咳嗽
1 回复 分享
发布于 05-06 18:48 上海
太好看啦!!!!
点赞 回复 分享
发布于 05-15 04:01 海南
点赞 回复 分享
发布于 05-27 13:07 湖南
没有循环依赖呀
点赞 回复 分享
发布于 06-25 20:45 山东
确实少了循环依赖
点赞 回复 分享
发布于 09-05 09:59 英国
11.11日已更新,订阅我专栏后可进入我的专栏里用md格式侧边栏看该笔记体验感更好!
点赞 回复 分享
发布于 11-11 17:42 湖南

相关推荐

11-05 16:19
已编辑
中山大学 算法工程师
点赞 评论 收藏
分享
10-24 19:32
西北大学 Java
点赞 评论 收藏
分享
换了个部门,每天有很多问题请教一位同事,她都很耐心,想表示感谢,送点啥给她呢,她也也不喝奶茶。一小束花二三十块的那种可以嘛?
耶耶耶耶只只:我是女生,我觉得你可以送盆好看的多肉植物,或者送个漂亮的小蛋糕(即使她不爱吃蛋糕,应该也会喜欢。因为我就是这样)
点赞 评论 收藏
分享
28 139 评论
分享
牛客网
牛客企业服务