其他资料
每日速记10道java面试题16-优快云博客
每日速记10道java面试题17-优快云博客
每日速记10道java面试题18-优快云博客
每日速记10道java面试题19-优快云博客
目录
3. 为什么Spring解决循环依赖要用到三级缓存,二级缓存不够吗?
9.Spring 中的 ObjectFactory 是什么?
10.Spring 中的 ApplicationContext 是什么?
1.什么是依赖循环?
循环依赖是指 Bean 对象循环引用,是两个或多个 Bean 之间相互持有对方的引用
举个例子,class A 中创建了个对象B,class B 中创建了个对象A
2.Spring 如何解决循环依赖?
关键就是提前暴露未完全创建完毕的 Bean。
在 Spring 中主要是使用三级缓存来解决了循环依赖:
- 一级缓存(Singleton Objects Map):用于存储完全初始化完成的单例Bean。
- 二级缓存(Eary singleton Objects Map):用于存储尚未完全初始化,但已实例化的Bean,用于提前暴露对象,避免循环依赖问题.
- 三级缓存(Singleton Factories Map):用于存储对象工厂,当需要时,可以通过工厂创建早Bean(特别是为了支持AOP代理对象的创建)。
解决步骤:
- Spring 首先创建 Bean 实例,并将其加入三级缓存中(Factory)。
- 当一个 Bean 依赖另一个未初始化的 Bean 时,Spring 会从三级缓存中获取 Bean 的工厂,并生成该 Bean 的代理对象。
- 代理对象存入二级缓存,解决循环依赖。
- 一旦所有依赖 Bean 被完全初始化,Bean 将转移到一级缓存中。
3. 为什么Spring解决循环依赖要用到三级缓存,二级缓存不够吗?
Spring 之所以需要三级缓存而不是简单的二级缓存,主要原因在于AOP代理和Bean的早期引用问题,二级缓存虽然可以解决循环依赖的问题,但在涉及到动态代理(AOP)时,直接使用二级缓存不做任何处理会导致我们拿到的 Bean 是未代理的原始对象。如果二级缓存内存放的都是代理对象,则违反了 Bean 的生命周期。
以下是二级缓存的思路:
以下是三级缓存解决循环依赖的思路:
1.创建Bean A,从一级缓存、二级缓存、三级缓存中查找,没找到,创建BeanA,将A放入三级缓存的0biectfactory里,此时A依赖于B,
2.从一、二、三级缓存中查找B,没找到,就创建BeanB,放入三级缓存ObjectFactory里,B依赖于A
3.从一、二、三级缓存中查找A,之前A在三级缓存中存在,查找到A,将其放入到二级缓存中(创建代理A),删除三级缓存的A
4.A填充Bean B的属性,此时B是完整的了,放入一级缓存中,删除三级缓存的B
5.B填充了开始的A,A也变成完整的了,放入到一级缓存中(A查找二级缓存中的代理A,变成代理A完整实例,存入到一级缓有
中,删除二级缓存的代理A)
6.返回A(代理A)
所以:
二级缓存可以解决普通Bean的循环依赖问题,但如果涉及到代理对象的循环依赖,就需要三级缓存来存储一个工厂对象,以便在解决循环依赖时生成代理对象。这样既保证了Bean的生命周期正常,又能够处理循环依赖的情况。
4.什么是Spring 的IOC?
Spring IOC (Inversion of Control,控制反转)是 Spring 框架的核心概念之一。它是通过依赖注入(Dependency Injection)实现的IOC 让对象的创建与管理职责由容器负责,而不是由对象自身控制。
核心思想:控制反转意味着将对象的创建和依赖关系交由 Spring 容器管理,而不是由程序代码直接控制。这种机制使得程序更加灵活和解耦,提升了代码的可维护性和扩展性。
依赖注入:通过构造器注入、setter 注入或接口注入,将对象所需的依赖传递给它,而不是让对象自行创建依赖。
延伸→IOC有什么好处?
对象的创建都由 I0C 容器来控制之后,对象之间就不会有很明确的依赖关系,使得非常容易设计出松耦合的程序。例如,对象 A需要依赖一个实现 B,但是对象都由 10℃ 控制之后,我们不需要明确地在对象 A的代码里写死依赖的实现 B,只需要写明依赖一个接口,这样我们的代码就能顺序的编写下去。
然后,我们可以在配置文件里定义A依赖的具体的实现 B,根据配置文件,在创建 A的时候,IOC容器就知晓 A 依赖的 B,这时候注入这个依赖即可。
如果之后你有新的实现需要替换,那A的代码不需要任何改动,你只需要将配置文件A依赖 B改成 B1,这样重启之后,IOC 容器会为A注入 B1.
这样就使得类 A 和类 B解耦了,very nice!
并目也因为创建对象由 IOC 全权把控,那么我们就能很方便的让IOC基于扩展点来“"加工”对象,例如我们要代理一个对象,IOC 在对象创建完毕,直接判断下这个对象是否需要代理,如果要代理,则直接包装返回代理对象。
这等于我们只要告诉 IOC 我们要什么,IOC 就能基于我们提供的配置文件,创建符合我们需求的对象正是这个控制反转的思想,解放了我们的双手。
总结一句话来说就是:资源不由使用资源者管理,而由不使用资源的第三方管理,这可以带来很多好处。第一,资源集中管理,实现资源的可配置和易管理。第二,降低了使用资源双方的依赖程度,也就是我们说的耦合度。
用生活中的例子就是,老板给员工发工资,不会找员工面对面发工资,员工也不会找老板面对面要工作,老板把钱给财务部,让财务部发工资。此时工资就是对象,财务部就是IOC容器。
5.什么是Spring的DI?
Dl(Dependency lnjection,依赖注入)普遍认为是 Spring 框架中用于实现控制反转(IOC)的一种机制。DI 的核心思想是由容器负责对象的依赖注入,而不是由对象自行创建或查找依赖对象。通过 Dl,Spring 容器在创建一个对象时,会自动将这个对象的依赖注入进去,这样可以让对象与其依赖的对象解耦,提升系统的灵活性和可维护性。
6.什么是spring的bean?
Spring Bean 是 Spring 框架中被管理的对象。它可以是任何符合特定规范的 Java 类实例。Spring 通过配置文件或注解等方式来定义和管理这些 Bean,实现了对象的创建、初始化、依赖注入以及生命周期的管理等功能。这样可以使得应用程序的组件之间更加松散耦合,提高了代码的可维护性和可扩展性。
延伸→讲一讲bean的生命周期?
实例化:当 Spring 容器启动时,根据配置文件或注解,Spring 会首先实例化 Bean。
依赖注入:在实例化之后,Spring 容器会通过构造器、setter 方法或注解将其他 Bean 的依赖注入进来。
初始化:如果 Bean 实现了 InitializingBean 接口或者使用了 @PostConstruct 注解,Spring 会在依赖注入完成后调用相应的初始化方法
销毁:如果 Bean 实现了 DisposableBean 接口或使用了 @PreDestroy注解,Spring 会在容器关闭时调用销毁方法。
延伸→怎么定义一个bean?
XML 配置:早期的 Spring 应用通常通过 XML 文件定义 Bean,使用<bean>标签来指定类、构造器参数和依赖关系。
基于注解的配置:使用 @Component、@Service、@Repository、@Controller 等注解可以将类标记为 Spring Bean,Spring 会自动扫描这些类并将其注册为 Bean。
Java 配置类:通过 @Configuration 和 @Bean 注解,可以在 Java 类中手动定义 Bean。相比,XML 配置,这种方式更加简洁和类型安全
7.Spring 中的 BeanFactory 是什么?
Beanfactory 其实就是 IOC的底层容器。负责管理和配置应用中的 Bean。它是 Spring IOC (控制反转)容器的基础实现,提供了创建和管理 Bean 的基本功能。通过 BeanFactory,Spring 容器可以按照需求加载和实例化 Bean。
简单来说就是bean的工厂,负责生成bean,它只会在Bean首次请求之后才会开始实例化该bean,并不是容器一启动就开始创建所有的bean。
8.Spring中的FactoryBean是什么?
FactoryBean 是 Spring 提供的一个特殊接口,允许开发者通过自定义的逻辑创建复杂的 Bean 实例。与普通的 Bean 不同,通过FactoryBean 创建的 Bean 不一定是 FactoryBean 本身,而是它生产的对象。
延伸→它跟BeanFactory有什么区别?
Beanfactory是IOC的底层容器,用于管理和获取bean实例,
而FactoryBean
是一个特殊的bean,用于创建和管理其他bean的实例。FactoryBean
提供了更多的自定义能力,允许在bean的创建过程中进行额外的逻辑处理。
9.Spring 中的 ObjectFactory 是什么?
Objectfactory 是一个接口,它可以用来进行bean的延迟加载。
他提供getobject方法返回一个bean实例,避免在spring容器创建时就加载bean对象。
懒加载
解决循环依赖时都使用了它
10.Spring 中的 ApplicationContext 是什么?
ApplicationContext是Spring框架中的一个核心接口,代表了Spring IOC容器的高级形态,提供了比BeanFactory更丰富的功能和灵活性。它是Spring应用程序的核心,不仅负责创建和管理Bean,还提供了对Bean的全面管理以及对应用程序环境的支持。ApplicationContext继承自BeanFactory接口,并在此基础上进行了扩展,提供了更多的功能和特性,如事件传播、国际化支持、资源加载、生命周期回调等。
ApplicationContext的主要功能和特点包括:
Bean的管理:负责管理应用程序中的所有Bean对象,包括它们的创建、配置、生命周期管理等
资源的加载:可以加载和管理各种资源,如配置文件、XML文件、Properties文件等,提供了一个统一的接口方便开发者访问和使用这些资源。
国际化支持:提供了国际化的支持,可以根据不同的语言环境加载不同的资源文件,实现多语言支持。
事件的发布与监听:可以发布事件,并允许其他组件注册监听器来处理这些事件,实现了组件之间的解。
AOP支持:提供了对面向切面编程(AOP)的支持,允许开发者通过配置切面来实现横切关注点的模块化。
ApplicationContext有多个实现类,如ClassPathXmlApplicationcontext和FilesystemXmlApplicationContext等,适用于不同的应用场景。通过这些实现类,开发者可以根据具体需求选择合适的Applicationcontext来实现Spring应用程序的各种功能。