ApplicationContextAware 类

2023-12-07 01:12

本文主要是介绍ApplicationContextAware 类,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

优质博文:IT-BLOG-CN

需求: 使用@autowired注入一些对象,但发现不可以直接使用@Autowired,因为方法是static的,要使用该方法当前对象也必须是static,正常情况下@Autowired无法注入静态的bean,于是发现项目中用到了springContextHolder,通过使用

private T t= SpringContextHolder.getBean(T.class);

或者我们在刚开始学习的时候,会使用如下这种方式来获取Bean。但是这样就会存在一个问题,因为它需要重新装载spring-core.xml文件,并实例化上下文bean,如果有些线程配置类也是在这个配置文件中,那么会造成做相同工作的的线程会被启两次。一次是 web容器初始化时启动,另一次是上述代码显示的实例化了一次。这样就产生了冗余。下面就来说说解决方案。

ApplicationContext appContext = new ClassPathXmlApplicationContext("spring-core.xml");  
T t = (T)appContext.getBean("t");  

一、SpringContextHolder 工具类

自定义SpringContextHolder工具类,全网统一模板。需要将该类注入到Spring IOC中。因此路径很重要。

package com.zzx.utils;import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;/*** @author* @date*/
@Component
@Slf4j
public class SpringContextHolder implements ApplicationContextAware, DisposableBean {private static ApplicationContext applicationContext = null;/*** 取得存储在静态变量中的ApplicationContext.*/public static ApplicationContext getApplicationContext() {assertContextInjected();return applicationContext;}/*** 从静态变量applicationContext中取得Bean, 自动转型为所赋值对象的类型.*/public static <T> T getBean(String name) {assertContextInjected();return (T) applicationContext.getBean(name);}/*** 从静态变量applicationContext中取得Bean, 自动转型为所赋值对象的类型.*/public static <T> T getBean(Class<T> requiredType) {assertContextInjected();return applicationContext.getBean(requiredType);}/*** 检查ApplicationContext不为空.*/private static void assertContextInjected() {if (applicationContext == null) {throw new IllegalStateException("applicaitonContext属性未注入, 请在applicationContext" +".xml中定义SpringContextHolder或在SpringBoot启动类中注册SpringContextHolder.");}}/*** 清除SpringContextHolder中的ApplicationContext为Null.*/public static void clearHolder() {log.debug("清除SpringContextHolder中的ApplicationContext:"+ applicationContext);applicationContext = null;}@Overridepublic void destroy() throws Exception {SpringContextHolder.clearHolder();}@Overridepublic void setApplicationContext(ApplicationContext applicationContext) throws BeansException {if (SpringContextHolder.applicationContext != null) {log.warn("SpringContextHolder中的ApplicationContext被覆盖, 原有ApplicationContext为:" + SpringContextHolder.applicationContext);}SpringContextHolder.applicationContext = applicationContext;}
}

二、ApplicationContextAware接口

Spring容器初始化的时候会检测容器中的所有Bean,如果发现某个Bean实现了ApplicationContextAware接口,Spring容器会在创建该Bean之后,自动调用该BeansetApplicationContextAware()方法,调用该方法时,会将容器本身作为参数传给该方法,该方法将Spring传入的参数(容器本身)赋给该类对象的applicationContext实例变量,因此接下来可以通过该applicationContext实例变量来访问容器本身。

三、BeanFactory

BeanFactorySpring的“心脏”。它就是Spring IoC容器的真面目。Spring使用BeanFactory来实例化、配置和管理BeanBeanFactoryIOC容器的核心接口,它定义了IOC的基本功能,我们看到它主要定义了getBean方法。getBean方法是IOC容器获取bean对象和引发依赖注入的起点。方法的功能是返回特定的名称的BeanBeanFactory只能管理单例Singleton Bean的生命周期。它不能管理原型prototype非单例Bean的生命周期。这是因为原型Bean实例被创建之后便被传给了客户端,容器失去了对它们的引用。

BeanFactory的源码:

public interface BeanFactory {// 用来引用一个实例,或把它和工厂产生的Bean区分开,就是说,如果一个FactoryBean的名字为a,那么,&a会得到那个Factory  四个不同形式的getBean方法,获取实例Object getBean(String var1) throws BeansException;<T> T getBean(String var1, Class<T> var2) throws BeansException;// 是否存在Object getBean(String var1, Object... var2) throws BeansException;<T> T getBean(Class<T> var1) throws BeansException;<T> T getBean(Class<T> var1, Object... var2) throws BeansException;<T> ObjectProvider<T> getBeanProvider(Class<T> var1);<T> ObjectProvider<T> getBeanProvider(ResolvableType var1);boolean containsBean(String var1);// 是否为单实例boolean isSingleton(String var1) throws NoSuchBeanDefinitionException;// 是否为原型(多实例)boolean isPrototype(String var1) throws NoSuchBeanDefinitionException;// 名称、类型是否匹配boolean isTypeMatch(String var1, ResolvableType var2) throws NoSuchBeanDefinitionException;boolean isTypeMatch(String var1, Class<?> var2) throws NoSuchBeanDefinitionException;// 获取类型@NullableClass<?> getType(String var1) throws NoSuchBeanDefinitionException;@NullableClass<?> getType(String var1, boolean var2) throws NoSuchBeanDefinitionException;// 根据实例的名字获取实例的别名String[] getAliases(String var1);
}

四、XmlBeanFactory

BeanFactory这是一个典型的工厂模式的工厂接口。BeanFactory最常见的实现类为XmlBeanFactory,可以从classpath或文件系统等获取资源。

File file = new File("fileSystemConfig.xml");
Resource resource = new FileSystemResource(file);
BeanFactory beanFactory = new XmlBeanFactory(resource);Resource resource = new ClassPathResource("classpath.xml"); 
BeanFactory beanFactory = new XmlBeanFactory(resource);

我们通过在applicationContext.xml中配置:

<bean id="car" class="spring.ioc.demo.Car" p:brand="xiaopeng" p:color="red" p:maxSpeed="520" />

通过XmlBeanFactory实现启动Spring IoC容器:

public static void main(String[] args) {// ResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();// Resource res = resolver.getResource("classpath:applicationContext.xml");// BeanFactory factory = new XmlBeanFactory(res);  ApplicationContext factory=new ClassPathXmlApplicationContext("applicationContext.xml"); Car car = factory.getBean("car", Car.class);
}

【1】XmlBeanFactory通过Resource装载Spring配置信息冰启动IoC容器,然后就可以通过factory.getBeanIoC容器中获取Bean了。
【2】通过BeanFactory启动IoC容器时,并不会初始化配置文件中定义的Bean,初始化动作发生在第一个调用时。
【3】对于单实例singletonBean来说,BeanFactory会缓存Bean实例,所以第二次使用getBean时直接从IoC容器缓存中获取Bean

五、ApplicationContext

如果说BeanFactorySpring的心脏,那么ApplicationContext就是完整的躯体了,ApplicationContextBeanFactory派生而来,提供了更多面向实际应用的功能。在BeanFactory中,很多功能需要以编程的方式实现,而在ApplicationContext中则可以通过配置实现。

BeanFactorty接口提供了配置框架及基本功能,但是无法支持springaop功能和web应用。而ApplicationContext接口作为BeanFactory的派生,因而提供BeanFactory所有的功能。而且ApplicationContext还在功能上做了扩展,相较于BeanFactortyApplicationContext还提供了以下的功能:
【1】MessageSource提供国际化的消息访问;
【2】资源访问,如URL和文件;
【3】事件传播特性,即支持aop特性;
【4】载入多个(有继承关系)上下文 ,使得每一个上下文都专注于一个特定的层次,比如应用的web层;

ApplicationContext:是IOC容器另一个重要接口, 它继承了BeanFactory的基本功能, 同时也继承了容器的高级功能,如:MessageSource(国际化资源接口)、ResourceLoader(资源加载接口)、ApplicationEventPublisher(应用事件发布接口)等。

六、总结

【1】BeanFactroy采用的是延迟加载形式来注入Bean的,即只有在使用到某个Bean时(调用getBean()),才对该Bean进行加载实例化,这样,我们就不能发现一些存在的Spring的配置问题。而ApplicationContext则相反,它是在容器启动时,一次性创建了所有的Bean。这样,在容器启动时,我们就可以发现Spring中存在的配置错误。 相对于基本的BeanFactoryApplicationContext唯一的不足是占用内存空间。当应用程序配置Bean较多时,程序启动较慢。
【2】BeanFacotry延迟加载,如果Bean的某一个属性没有注入,BeanFacotry加载后,直至第一次使用调用getBean方法才会抛出异常;而ApplicationContext则在初始化自身是检验,这样有利于检查所依赖属性是否注入;所以通常情况下我们选择使用ApplicationContext
【3】应用上下文则会在上下文启动后预载入所有的单实例Bean。通过预载入单实例bean,确保当你需要的时候,你就不用等待,因为它们已经创建好了。
【4】BeanFactoryApplicationContext都支持eanPostProcessorBeanFactoryPostProcessor的使用,但两者之间的区别是:BeanFactory需要手动注册,而ApplicationContext则是自动注册。ApplicationcontextbeanFactory加入了一些更好使用的功能。而且 beanFactory的许多功能需要通过编程实现而Applicationcontext可以通过配置实现。比如后处理beanApplicationcontext直接配置在配置文件即可而beanFactory这要在代码中显示的写出来才可以被容器识别。
【5】beanFactory主要是面对与spring框架的基础设施,面对spring自己。而Applicationcontex主要面对与spring使用的开发者。基本都会使用Applicationcontex并非beanFactory

这篇关于ApplicationContextAware 类的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/464002

相关文章

Spring源码学习--Aware相关接口(beanNameAware接口/BeanFactoryAware接口/ApplicationContextAware接口)

可以先这样理解在Spring中以Aware结尾的接口的功能 看到Spring源码中接口以Aware结尾的接口(XXXAware)在Spring中表示对XXX可以感知,通俗点解释就是:如果在某个类里面想要使用spring的一些东西,就可以通过实现XXXAware接口告诉Spring,Spring看到后就会给你送过来,而接收的方式是通过实现接口唯一方法set-XXX.比如:有一个类想要使用当前

SpringBoot基础篇(三)ApplicationContextAware和CommandLineRunner接口

1.ApplicationContextAware接口         ApplicationContext对象是Spring开源框架的上下文对象实例,在项目运行时自动装载Handler内的所有信息到内存。基于SpringBoot平台完成ApplicationContext对象的获取,并通过实例手动获取Spring管理的bean。 ApplicationContextAware接口的方式获取A

Spring应用 4 ApplicationContextAware应用理解

Spring应用 4  ApplicationContextAware应用理解 Aware接口的Bean在被初始之后,可以取得一些相对应的资源。 Aware接口本身并不具备什么功能,一般是用于子类继承后,Spring上下文初始化bean的时候会对这个bean传入需要的资源。 例如ApplicationContextAware接口,可以在Spring初始化实例 Bean的时候,可以通过这个接口将当

实现ApplicationContextAware接口完成springboot项目的初始化处理工作

需求:在项目启动的时候,从数据库里取出所有敏感词,放到map里面。 ApplicationContextAware 的实现类的setApplicationContext方法可以获取到IOC容器,虽然这个案例里面并没有什么用,但是项目初始化一般实现ApplicationContextAware 接口 核心代码 @Componentpublic class InitLoadService

【SpringBoot】ApplicationContextAware 与 @Autowired 注解效果是一样,但是时机不一样

一、区别 ApplicationContextAware 是一个接口,它提供一个方法 setApplicationContext ,当 spring 注册完成之后,会把 ApplicationContext 对象以参数的方式传递到方法里,在方法里我们可以实现自己的逻辑,去获取自己的 bean,当前对接的断言等;一般用在被封装的工具包, starter 包中,方便给其它开发人员调用。@Autowi

【Spring】16 ApplicationContextAware 接口

文章目录 1. 简介2. 作用3. 使用3.1 创建并实现接口3.2 配置 Bean 信息3.3 创建启动类3.4 启动 4. 应用场景总结 Spring 框架提供了许多回调接口,用于在 Bean 的生命周期中执行特定的操作。ApplicationContextAware 接口是其中之一,它允许 Bean 获取对 ApplicationContext 的引用。本文将介绍 App

【Spring】15 ApplicationContextAware 接口

文章目录 1. 简介2. 作用3. 使用3.1 创建并实现接口3.2 配置 Bean 信息3.3 创建启动类3.4 启动 4. 应用场景总结 Spring 框架提供了许多回调接口,用于在 Bean 的生命周期中执行特定的操作。ApplicationContextAware 接口是其中之一,它允许 Bean 获取对 ApplicationContext 的引用。本文将介绍 App

依赖注入的进阶:深度解析ApplicationContextAware

1. ApplicationContextAware是什么 ApplicationContextAware 是Spring框架中的一个接口,它允许Spring管理的Bean获取对应用程序上下文(ApplicationContext)的访问权限。应用程序上下文是Spring框架的核心容器,负责管理Bean的生命周期、依赖注入以及提供各种服务。 2.为了解决什么问题 ApplicationCon

ApplicationContextAware、ApplicationContext

ApplicationContextAware ApplicationContextAware接口是Spring框架中的一个接口,用于获取ApplicationContext对象,从而可以在应用程序中访问Spring容器的功能。 该接口定义了一个方法setApplicationContext(ApplicationContext applicationContext),当Spring容器初始化