0


SpringBean详解

文章目录

概述

Spring Bean 是 Spring 框架中的核心概念之一,它表示由 Spring 容器管理的对象。Spring Bean 可以是任何 Java 类的实例,包括简单的 JavaBean、业务逻辑对象、数据访问对象、甚至是整合了第三方库或框架的对象。以下是关于 Spring Bean 的详细解释:

  1. Bean 定义(Bean Definition):Spring Bean 通过 Bean 定义来描述。Bean 定义是一个配置元数据,它包含了创建和配置 Bean 的信息,包括 Bean 的类名、依赖关系、初始化方法、销毁方法等。
  2. Bean 的生命周期:Spring 容器负责管理 Bean 的生命周期,包括 Bean 的创建、初始化、使用和销毁等阶段。可以通过配置初始化方法和销毁方法来控制 Bean 的生命周期。
  3. 依赖注入(Dependency Injection):Spring 容器负责管理 Bean 之间的依赖关系,可以通过依赖注入将一个 Bean 注入到另一个 Bean 中。依赖注入可以通过构造函数、Setter 方法或字段注入的方式来实现。
  4. 作用域(Scope):Spring 提供了多种作用域来管理 Bean 的生命周期,包括单例(Singleton)、原型(Prototype)、会话(Session)、请求(Request)等。默认情况下,Bean 的作用域是单例。
  5. 初始化和销毁方法:可以通过配置初始化方法和销毁方法来控制 Bean 的初始化和销毁过程。初始化方法在 Bean 创建后立即执行,销毁方法在容器关闭时执行。
  6. Bean 的装配方式:Spring 提供了多种装配 Bean 的方式,包括 XML 配置、注解(Annotation)和 Java 配置(Java Config)等。可以根据实际需求选择合适的装配方式。
  7. Bean 的自动装配(Autowiring):Spring 提供了自动装配的功能,可以根据类型、名称等条件自动将 Bean 注入到目标 Bean 中,减少了手动配置的工作量。
  8. Bean 的后置处理器(BeanPostProcessor):Spring 允许开发者在 Bean 初始化前后执行自定义逻辑,可以通过 Bean 后置处理器来实现对 Bean 的定制化处理。 总的来说,Spring Bean 是 Spring 框架的核心组件之一,它通过依赖注入、作用域管理等功能,实现了松耦合、灵活性和可测试性,是 Spring 应用程序的基础构建块之一。

Spring获取Bean的流程

1、加载配置,可以是xml配置或者是配置类,Spring提供了统一的抽象接口BeanDefinitionReader,对于不同的配置有不同的实现类,xml配置是使用XmlBeanDefinitionReader,然后将Bean解析成BeanDefinition对象,然后注册到beanDefinitionMap中,key就是bean的id,value就是BeanDefinition对象,如果有别名的话,在map额外保存一个key是别名,value是id,获取Bean的时候会重定向一次
1、扫描 ----> 创建BeanDefinition对象 ———>放到beanDefinitionMap中
xml配置或者注解
BeanDefinition
实例化Bean
属性注入
初始化
Bean被调用
销毁
Spring中的bean的生命周期主要包含四个阶段:实例化Bean --> Bean属性填充 --> 初始化Bean -->销毁Bean

依赖注入

Spring beans 是那些形成Spring应用的主干的java对象。它们被Spring IOC容器初始化,装配, 和管理。这些beans通过容器中配置的元数据创建。比如,以XML文件中 的形式定义
依赖注入
构造函数注入
setter 注入
接口注入
在 Spring Framework 中,仅使用构造函数和 setter 注入。
依赖注入是时下最流行的IOC实现方式,依赖注入分为接口注入(Interface Injection),Setter方
法注入(Setter Injection)和构造器注入(Constructor Injection)三种方式。其中接口注入由于
在灵活性和易用性比较差,现在从Spring4开始已被废弃。
构造器依赖注入:构造器依赖注入通过容器触发一个类的构造器来实现的,该类有一系列参数,每
个参数代表一个对其他类的依赖。
Setter方法注入:Setter方法注入是容器通过调用无参构造器或无参static工厂 方法实例化bean之
后,调用该bean的setter方法,即实现了基于setter的依赖注入。
Spring基于xml注入bean的几种方式

  1. Set方法注入
  2. 构造器注入:
  3. 通过index设置参数的位置;
  4. 通过type设置参数类型;
  5. 静态工厂注入;
  6. 实例工厂; 将Bean注入到Spring的容器中的方式 ● @Configuration + @Bean ● @ComponentScan + @Component ● @Import 配合接口进行导入 ● 使用FactoryBean。 ● 实现BeanDefinitionRegistryPostProcessor进行后置处理。

1、@Configuration + @Bean
2、@Component + @ComponentScan
3、@Import注解导入
3.1 Import直接导入类
3.2@Import + ImportSelector
3.3@Import + ImportBeanDefinitionRegistrar
3.4@Import + DeferredImportSelector
4、使用FactoryBean接口
5、使用 BeanDefinitionRegistryPostProcessor

SpringBean配置方式有哪些
1.基于 xml 配置
2.java api方式
3.注解的的方式

bean的作用域

Spring容器中的bean可以分为5个范围:
(1)singleton:默认,容器初始化时创建bean实例,在整个容器的生命周期内只创建这个bean,单例的,每个容器中只有一个bean的实例,单例的模式由BeanFactory自身来维护。
(2)prototype:为每一个bean请求提供一个实例,翻译成原型,意味着每次从IOC容器去获取指定Bean的时候,都会返回一个新的实例对象。原型的, 容器初始化时不创建bean实例,而在每次请求时都创建一个新的bean实例,并返回
(3)request:为每一个网络请求创建一个实例,在请求完成以后,bean会失效并被垃圾回收器回收。
(4)session:与request范围类似,确保每个session中有一个bean的实例,在session过期后,bean会随之失效。
(5)global-session:全局作用域,global-session和Portlet应用相关。当你的应用部署在Portlet容器中工作时,它包含很多portlet。如果你想要声明让所有的portlet共用全局的存储变量的话,那么这全局变量需要存储在global-session中。全局作用域与Servlet中的session作用域效果相同。

bean对象的作用范围(掌握) scope

  1. singleton: 单例 代表在SpringIOC容器中只有一个Bean实例 (默认的scope)
  2. prototype多例 每一次从Spring容器中获取时,都会返回一个新的实例
  3. request 用在web开发中,将bean对象request.setAttribute()存储到request域中
  4. session 用在web开发中,将bean对象session.setAttribute()存储到session域中

关于Bean生命周期:
Spring 根据 Bean 的作用域来选择管理方式。对于 singleton 作用域的 Bean,Spring 能够精确地知道该 Bean 何时被创建,何时初始化完成,以及何时被销毁;而对于 prototype 作用域的 Bean,Spring 只负责创建,当容器创建了 Bean 的实例后,Bean 的实例就交给客户端代码管理,Spring 容器将不再跟踪其生命周期。
验证了:对于 prototype 作用域的 Bean,Spring 只负责创建,当容器创建了 Bean 的实例后,Bean 的实例就交给客户端代码管理,Spring 容器将不再跟踪其生命周期。
Spring 只负责创建,所以它调用了初始而不会调用销毁方法,又同时验证了原型模式每次通过 Spring 容器获取 Bean 时,容器都会创建一个 Bean 实例,所以会调用两次初始化方法。

Spring 中的 Bean 是线程安全的吗

在 Spring 框架中,Bean 的线程安全性不是由 Spring 自身保证的,而是取决于 Bean 的实现方式。Spring 容器负责管理 Bean 的生命周期,包括创建、初始化、销毁等过程,但它并不会对 Bean 的线程安全性进行特殊处理。
Bean 的线程安全性取决于以下几个方面:

  1. Bean 的作用域(Scope):Spring 支持多种作用域,如单例(Singleton)、原型(Prototype)、请求(Request)和会话(Session)等。其中,单例作用域的 Bean 在整个 Spring 容器中只有一个实例,多个线程可能同时访问该实例,因此需要特别注意线程安全问题。对于原型作用域的 Bean,每次请求都会创建一个新的实例,因此不存在线程安全问题。
  2. Bean 的状态:无状态(Stateless)的 Bean 通常是线程安全的,因为它们不保存任何与特定请求相关的状态信息。而有状态(Stateful)的 Bean 可能需要在多线程环境下进行同步处理,以确保线程安全。
  3. 线程安全类库和同步机制:如果 Bean 依赖于线程安全类库(如 java.util.concurrent 包中的类)或者使用了同步机制(如 synchronized 关键字),那么这些 Bean 可能具有更好的线程安全性。 总之,要确保 Spring 中的 Bean 在多线程环境下的线程安全性,需要关注 Bean 的作用域、状态以及所使用的线程安全类库和同步机制。在实际开发中,如果 Bean 是有状态的且作用域为单例,建议使用同步机制来确保线程安全。如果可能的话,尽量将 Bean 设计为无状态的,以降低线程安全问题的风险。 不是,Spring框架中的单例bean不是线程安全的。 spring 中的 bean 默认是单例模式,spring 框架并没有对单例 bean 进行多线程的封装处理。 实际上大部分时候 spring bean 无状态的(比如 dao 类),所有某种程度上来说 bean 也是安全 的,但如果 bean 有状态的话(比如 view model 对象),那就要开发者自己去保证线程安全了, 最简单的就是改变 bean 的作用域,把“singleton”变更为“prototype”,这样请求 bean 相当于 new Bean()了,所以就可以保证线程安全了。 有状态就是有数据存储功能。 无状态就是不会保存数据。 Prototype的Bean是线程安全的,无状态的Singleton的Bean是线程安全的。有状态的Singleton的Bean是非线程安全的。 在Spring框架中,Bean的线程安全性取决于具体的Bean定义和作用域。 默认情况下,Spring中的Bean是单例模式的,也就是说容器中只有一个实例,多个线程共享该实例。在这种情况下,如果Bean没有状态并且不依赖于外部资源,那么它是线程安全的。例如,一个只提供读取操作而没有写入操作的工具类。 然而,如果Bean具有可变的状态或者依赖于外部资源(如数据库连接、文件等),那么它可能是线程不安全的。在这种情况下,你需要采取适当的措施来确保线程安全性,比如使用同步机制(synchronization)或者使用线程安全的数据结构。 此外,Spring还提供了其他作用域以支持多例模式和原型模式的Bean。如果将Bean定义为多例或原型作用域,那么每次请求Bean时都会创建一个新的实例,因此它们可以更好地支持并发环境。 总之,Spring中的Bean的线程安全性是由具体的实现和作用域决定的。对于有状态的Bean,你需要根据实际情况采取适当的线程安全措施来确保其正确性。

Spring如何处理线程并发问题

在一般情况下,只有无状态的Bean才可以在多线程环境下共享,在Spring中,绝大部分Bean都可
以声明为singleton作用域,因为Spring对一些Bean中非线程安全状态采用ThreadLocal进行处理,解决线程安全问题。
ThreadLocal和线程同步机制都是为了解决多线程中相同变量的访问冲突问题。同步机制采用了
“时间换空间”的方式,仅提供一份变量,不同的线程在访问前需要获取锁,没获得锁的线程则需要
排队。而ThreadLocal采用了“空间换时间”的方式。
ThreadLocal会为每一个线程提供一个独立的变量副本,从而隔离了多个线程对数据的访问冲突。
因为每一个线程都拥有自己的变量副本,从而也就没有必要对该变量进行同步了。ThreadLocal提
供了线程安全的共享对象,在编写多线程代码时,可以把不安全的变量封装进ThreadLocal

bean 的自动装配和方式

无须在 Spring 配置文件中描述 javaBean 之间的依赖关系(如配置、)。IOC容器会自动建立 javabean 之间的关联关系。Spring 装配包括手动装配和自动装配,手动装配是有基于 xml 装配、构造方法、setter 方法等自动装配有五种自动装配的方式,可以用来指导 Spring 容器用自动装配方式来进行依赖注入 解释不同方式的自动装配五种自动装配的方式
可以用来指导 Spring 容器用自动装配方式来进行依赖注入。
1)no:默认的方式是不进行自动装配,通过显式设置 ref 属性来进行装配。
2)byName:通过参数名自动装配,Spring 容器在配置文件中发现 bean 的 autowire 属性被设置成 byname,
之后容器试图匹配、装配和该 bean 的属性具有相同名字的 bean。
3)byType::通过参数类型自动装配,Spring 容器在配置文件中发现 bean 的 autowire 属性被设置成 byType,之后容器试图匹配、装配和该 bean 的属性具有相同类型的 bean。如果有多个 bean 符合条件,则抛出错误。
4)constructor:这个方式类似于 byType, 但是要提供给构造器参数,如果没有确定的带参数的构造器参数类
型,将会抛出异常。
5)autodetect:首先尝试使用 constructor 来自动装配,如果无法工作,则使用 byType 方式

@Resource和@Autowired的区别

1.注解内部定义的参数不同
@Autowired只包含一个required参数,默认为true,表示开启自动注入
而@Resource 包含七个参数,其中最重要的两个是name和type。
2、装配方式的默认值不同
@Autowired默认按type自动装配,而@Resource默认按name自动装配。当然,@Resource注解可以自
定义选择,如果指定了name,则根据name自动装配,如果指定了type,则用type自动装配。
3、注解应用的范围不同
@Autowired能够用在构造方法、成员变量、方法参数以及注解上,而@Resource能用在类、成员变量和
方法参数上,这点从源码也能看得出来。
4.出处不同
@Autowired是Spring定义的注解,而@Resource是遵循JSR-250规范,定义在JDK中。所以
@Autowired只能在Spring框架下使用,而@Resource则可以与其他框架一起使用。
5.装载顺序不同
@Autowired默认先按byType进行匹配,如果发现找到多个bean,则又按照byName方式进行匹配,如
果还有多个,则报出异常。
@Resource 先按 byName 再按byType
在日常开发中,我建议使用@Autowired,有以下三个理由:
第1:@Autowired功能略强大。支持优先注入、可以配置允许bean不存在。
第2:若使用了Spring框架,使用其特有的注解个人感觉更好一点。
第3:有人会认为@Resource更加通用,因为它是个规范,其他框架也会支持。但我认为,目前后端都是在用Spring了,没有必要考虑其他框架。

byName和byType的区别
● byName的时候,需要保证所有的bean的id唯一,并且这个bean需要和自动注入的属性的set方法的值一致
● byType的时候,需要保证所有的bean的class唯一,并且这个bean需要和自动注入的属性的类型一致
@Autowired(required=false)注入注意的问题
@Autowired(required=false):表示忽略当前要注入的bean,如果有直接注入,没有跳过,不会报错。

bean的自动装配

  1. 在xml中显示的配置
  2. 在Java中显示配置
  3. 隐式的自动装配bean

bean的生命周期

1.实例化Bean对象:反射的方式生成对象
2.填充bean的属性:populateBean(),循环依赖的问题(三级缓存)
3.调用Aware接口相关的方法:invokeAwareMethod(完成BeanName,BeanFactory,BeanClassLoder对象的属性设置)
4.调用BeanPostProcessor中的前置处理方法:使用比较多的有(ApplicationContextPostProcessor,设置ApplicationContext,Environment,ResourceLoader,EmbeddValueResolver等对象)
5.调用initmethod方法:invokeInitmethod(),判断是否实现了initializingBean接口,如果有,调用afterPropertiesSet方法,没有就不调用
6.调用BeanPostProcess的后置处理方法:spring的aop就是在此处实现的,AbstractAutoProxyCreator
注册Destuction相关的回调接口:钩子函数
7.获取到完整的对象,可以通过getBean的方式来进行对象的获取
8.销毁流程: 1.判断是否实现了DispoableBean接口,2.调用destroyMethod方法

1.创建前准备阶段
这个阶段主要是在开始Bean加载之前,从Spring上下文和相关配置中解析并查找Bean有关的配置内容,
比如

init-method

-容器在初始化bean时调用的方法、

destory-method

,容器在销毁Bean时调用的方
法。以及,BeanFactoryPostProcessor这类的bean加载过程中的前置和后置处理。这些类或者配置其实是Spring提供给开发者,用来实现Bean加载过程中的扩展机制,在很多和Spring集成的中间件经常使用,比如Dubbo。
2.创建实例阶段
这个阶段主要是通过反射来创建Bean的实例对象,并且扫描和解析Bean声明的一些属性。
3、依赖注入阶段
在这个阶段,会检测被实例化的Bean是否存在其他依赖,如果存在其他依赖,1就需要对这些被依赖Bean进行
注入。比如通过读取@Autowired`、@Setter等依赖注入的配置。在这个阶段还会触发一些扩展的调用,比如常见的扩展类:BeanPostProcessors

(用来实现Bean初始化前后的回调)、InitializingBean类(这个类有一个afterPropertiesSet()方法,给属性赋值)、还BeanFactoryAware等等。
4.容器缓存阶
容器缓存阶段主要是把Bean保存到IoC容器中缓存起来,到了这个阶段,Bean就可以被开发者使用了。
这个阶段涉及到的操作,常见的有,

init-method

这个属性配置的方法,会在这个阶段调用。在比如BeanPostProcessors方法中的后置处理器方法如:postProcessAfterInitialization,也是在这个阶段触
发的。
5.销毁实例阶段
这个阶段,是完成Spring应用上下文关闭时,将销毁Spring上下文中所有的Bean。
如果Bean实现了DisposableBean接口,或者配置了

destory-method

属 性,将会在这个阶段被调用。

Spring 中的 bean 生命周期
Bean的生命周期是由容器来管理的。主要在创建和销毁两个时期。
spring bean 容器的生命周期流程如下:
1)Spring 容器根据配置中的 bean 定义中实例化 bean。
2)Spring 使用依赖注入填充所有属性,如 bean 中所定义的配置。
3)如果 bean 实现 BeanNameAware 接口,则工厂通过传递 bean 的 ID 来 调用 setBeanName()。
4)如果 bean 实现 BeanFactoryAware 接口,工厂通过传递自身的实例来调用setBeanFactory()。
5)如果存在与 bean 关联的任何 BeanPostProcessors,则调用 preProcessBeforeInitialization() 方法。
6)如果为 bean 指定了 init 方法( 的 init-method 属性),那么将调用它。
7)最后,如果存在与 bean 关联的任何 BeanPostProcessors,则将调用 postProcessAfterInitialization() 方法。
8)如果 bean 实现 DisposableBean 接口,当 spring 容器关闭时,会调用 destory()。
9)如果为 bean 指定了 destroy 方法( 的 destroy-method 属 性),那么将 调用它

BeanFactory

Spring里面的核心功能是IOC容器,所谓IOC容器呢,本质上就是一个Bean的容器或者是一个Bean的工厂。它能够根据xml里面声明的Bean配置进行bean的加载和初始化,然后BeanFactory来生产我们需要的各种各样的Bean。
BeanFactory是所有Spring Bean容器的顶级接口,它为Spring的容器定义了一套规范,并提供像getBean这样的方法从容器中获取指定的Bean实例。BeanFactory在产生Bean的同时,还提供了解决Bean之间的依赖注入的能力,也就是所谓的DI。
FactoryBean是一个工厂Bean,它是一个接口,主要的功能是动态生成某一个类型的Bean的实例,也就是说,我们可以自定义一个Bean并且加载到IOC容器里面。它里面有一个重要的方法叫getObject(),这个方法里面就是用来实现动态构建Bean的过程。
Spring Cloud里面的OpenFeign组件,客户端的代理类,就是使用了FactoryBean来实现的

BeanFactory 常用的实现类有哪些

Bean 工厂是工厂模式的一个实现,提供了控制反转功能,用来把应用的配置和依赖从正真的应用代码中分离。常
用的 BeanFactory 实现有 DefaultListableBeanFactory 、 XmlBeanFactory 、 ApplicationContext 等。
XMLBeanFactory,最常用的就是 org.springframework.beans.factory.xml.XmlBeanFactory ,它根据 XML 文件中的定义加载 beans。该容器从 XML 文件读取配置元数据并用它去创建一个完全配置的系统或应用。

ApplicationContext 的实现类有哪些
FileSystemXmlApplicationContext :此容器从一个 XML 文件中加载 beans 的定义,XML Bean 配置文件的全
路径名必须提供给它的构造函数。
ClassPathXmlApplicationContext:此容器也从一个 XML 文件中加载 beans 的定义,这里,你需要正确设置
classpath 因为这个容器将在 classpath 里找 bean 配置。
WebXmlApplicationContext:此容器加载一个 XML 文件,此文件定义了一个 WEB 应用的所有 bean。

BeanFactory与FactoryBean的不同

1、BeanFactory和FactoryBean都是接口
2、BeanFactory就是Spring的Bean工厂,创建并保存了我们的Bean对象,
3、而FactoryBean是Spring提供的专门创建那些复杂对象的,复杂对象即不能直接使用new关键字创建的对象,比如说Connection对象,SqlSessionFactory对象,我们需要实现FactoryBean接口,主要是重写getObject()方法,写创建对象的代码,然后将这个实现类配置在配置文件或者使用配置类的形式,我们获取工厂后使用getBean(“id”)的方式获取的就是这个实现类为我们创建的复杂对象,如果想要获取这个实现类对象,在getBean()获取Bean时id前加入&即可

ApplicationContextAware常用的IOC容器

ApplicationContext是我们常用的IOC容器,而他的顶层接口便是BeanFactory,ApplicationContext对BeanFactory做了拓展,功能更加强大
2、ApplicationContextAware作用
在Spring/SpringMVC中,我们拿到IOC容器无非有三种方式,那就是使用ApplicationContext接口下的三个实现类:ClassPathXmlApplicationContext、FileSystemXmlApplicationContext、AnnotationConfigApplicationContext(我的思维导图有对IOC核心容器的介绍:Spring知识点)。
SpringMVC中还好,虽然可以自动初始化容器,但是我们依旧可以通过那三个实现类获取ApplicationContext对象,但是在SpringBoot中,因为没有了ioc配置文件,全都成自动化的了,我们无法通过上述方式拿到ApplicationContext对象,但有时候遇到的需求是必须要通过Spring容器才能实现的,例如动态获取三方渠道的代理类,所以,简单地说,ApplicationContextAware接口是用来获取框架自动初始化的ioc容器对象的。
ApplicationContextAware如何使用
注解方式当下用的比较多,所以我就不提xml方式的了,写个类实现ApplicationContextAware接口,实现方法,再提供几个ioc容器常用方法,将这个类当工具类用,描述不如看代码:

package com.wangxs.springcloud.utils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;

@Component
@Slf4j
public class AppContextUtil implements ApplicationContextAware {
    // 定义静态ApplicationContext
    private static ApplicationContext applicationContext = null;
    /**
     * 重写接口的方法,该方法的参数为框架自动加载的IOC容器对象
     * 该方法在启动项目的时候会自动执行,前提是该类上有IOC相关注解,例如@Component
     * @param applicationContext ioc容器
     * @throws BeansException e
     */
    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        // 将框架加载的ioc赋值给全局静态ioc
        AppContextUtil.applicationContext = applicationContext;
        log.info("==================ApplicationContext加载成功==================");
    }
    // 获取applicationContext
    public static ApplicationContext getApplicationContext() {
        return applicationContext;
    }
    // 通过name获取 Bean.
    public static Object getBean(String name) {
        return getApplicationContext().getBean(name);
    }
    // 通过class获取Bean.
    public static <T> T getBean(Class<T> clazz) {
        return getApplicationContext().getBean(clazz);
    }
    // 通过name,以及Clazz返回指定的Bean
    public static <T> T getBean(String name, Class<T> clazz) {
        return getApplicationContext().getBean(name, clazz);
    }  
}
SpringContextUtil.getBean(ConfigCache.class);

知识点拓展
Spring中ioc容器是在我们通过上述三个类拿到ApplicationContext对象时进行初始化的,属于手动初始化,而在SpringMvc中,我们不再需要手动初始化,项目启动即加载了IOC容器,本质上是利用了JavaWeb的监听技术。
ServletContextListener是对JavaWeb域对象ServletContext的监听,而ServletContext对象整个服务器仅一份且在服务器启动便加载,而SpringMvc也设定了监听ContextLoaderListener,这个类实现了ServletContextListener接口,如此一来,SpringMvc便能感知到ServletContext对象要创建了,服务器要启动了,此时该加载IOC容器了。

1、ApplicationContext是BeanFactory的子接口
2、 BeanFactory是工厂接口,负责创建Bean的实例,并保存这些单实例的bean在Map中
3、ApplicatonContext是容器的接口,比BeanFactory功能更加强大,更多的负责容器功能的实现,可以基于BeanFactory创建好的对象之上完成强大的容器,AOP DI都是ApplicatonContext接口下的这些类里,
BeanFactory是最底层的接口,ApplicatonContext是留给我们使用的ioc容器接口。

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

1.BeanFactroy采用的是延迟加载形式来注入Bean的,即只有在使用到某个Bean时(调用getBean()),才对该Bean进行加载实例化,这样,我们就不能发现一些存在的Spring的配置问题。而ApplicationContext则相反,它是在容器启动时,一次性创建了所有的Bean。这样,在容器启动时,我们就可以发现Spring中存在的配置错误。 相对于基本的BeanFactory,ApplicationContext 唯一的不足是占用内存空间。当应用程序配置Bean较多时,程序启动较慢。
BeanFacotry延迟加载,如果Bean的某一个属性没有注入,BeanFacotry加载后,直至第一次使用调用getBean方法才会抛出异常;而ApplicationContext则在初始化自身是检验,这样有利于检查所依赖属性是否注入;所以通常情况下我们选择使用 ApplicationContext。应用上下文则会在上下文启动后预载入所有的单实例Bean。通过预载入单实例bean ,确保当你需要的时候,你就不用等待,因为它们已经创建好了。

2.BeanFactory和ApplicationContext都支持BeanPostProcessor、BeanFactoryPostProcessor的使用,但两者之间的区别是:BeanFactory需要手动注册,而ApplicationContext则是自动注册。(Applicationcontext比 beanFactory 加入了一些更好使用的功能。而且 beanFactory 的许多功能需要通过编程实现而 Applicationcontext 可以通过配置实现。比如后处理 bean , Applicationcontext 直接配置在配置文件即可而 beanFactory 这要在代码中显示的写出来才可以被容器识别。 )

3.beanFactory主要是面对与 spring 框架的基础设施,面对 spring 自己。而 Applicationcontex 主要面对与 spring 使用的开发者。基本都会使用 Applicationcontex 并非 beanFactory 。
因此,在实际开发中,通常都选择使用 ApplicationContext,而只有在系统资源较少时,才考虑使用 BeanFactory。
除了提供BeanFactory所具有的功能外,还提 供了更完整的框架功能:
继承MessageSource,因此支持国际化
统一的资源文件访问方式
提供在监听器中注册bean的事件
同时加载多个配置文件
载入多个(有继承关系)上下文 ,使得每一个上下文都专注于一个特定的层次,比如应用的 web层

BeanFactory和ApplicationContext区别
applicationcontext对BeanFactory实现额外增强
applicationcontext主动添加Bean(工厂)处理器 来完成扫包
applicationcontext主动添加bean处理器 ----依赖注入@Autowired
applicationcontext主动初始化单例对象
BeanFactory----bean定义信息、单例池

  1. BeanFactory是ApplicationContext的顶层接口
  2. BeanFactory是采用延迟加载策略.只有真正使用getBean时才会实例化Bean.适用于多例模式
  3. ApplicationContext配置文件加载时就会立即初始化Bean,适用于单例模式,实际开发时一般采用这种. 常用的三个实现类(熟悉)
  4. ClassPathXmlApplicationContext:加载类路径下的配置文件,要求配置文件必须在类路径下(常用)
  5. FileSystemXmlApplicationContext:加载磁盘任意路径下的配置文件(必须有访问权限)
  6. AnnotationConfigApplicationContext:读取注解配置容器

BeanFactory基础类型的 IOC 容器,提供完成的 IOC 服务支持。如果没有特殊指定,默认采用延迟初始化策略。相对来说,容器启动初期速度较快,所需资源有限
BeanFactory是Spring里面最底层的接口,是Ioc的核心,定义了Ioc的基本功能,包含了各种Bean的定义、加载、实例化,依赖注入和生命周期管理;

ApplicationContext 是在 BeanFactory 的基础上构建,是相对比较高级的容器实现,除了 BeanFactory 的所有
支持外,ApplicationContext 还提供了事件发布、国际化支持等功能。ApplicationContext 管理的对象,在容器启动后默认全部初始化并且绑定完成。
ApplicationContext接口作为BeanFactory的子类,除了提供BeanFactory所具有的功能外,还提供了更完整的框架功能
①继承MessageSource,因此支持国际化
②资源文件访问,如URL和文件(ResourceLoader)
③载入多个(有继承关系)上下文(及同时加载多个配置文件),使得每一个上下文都专注于一个特定的层次
④提供在监听器中注册bean的事件;

标签: spring java

本文转载自: https://blog.csdn.net/Fireworkit/article/details/138676099
版权归原作者 思静语 所有, 如有侵权,请联系我们删除。

“SpringBean详解”的评论:

还没有评论