Spring应用 4 ApplicationContextAware应用理解

2024-06-15 07:48

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

Spring应用 4  ApplicationContextAware应用理解

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

注意:一定要让继承ApplicationContextAware接口的bean被Spring上下文管理,在application.xml文件中定义对应的bean标签,或者使用@Component标注。

ApplicationContextAware的使用
1.实现ApplicationContextAware接口,创建一个类实现 这个接口ApplicationContextAware, 在该类中定义ApplicationContext静态变量 。并对setApplicationContext方法进行重写。

通过在实现ApplicationContextAware在组件bean初始化的时候传入ApplicationContext,这样可以根据ApplicationContext中的一些数据进行一些自定义的操作
@Component
public class ControllerTest implements ApplicationContextAware {
     private static ApplicationContext applicationContext;
     private static ClassPathXmlApplicationContext XapplicationContext;

     @Override
     public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
           this.applicationContext = applicationContext;
           this.XapplicationContext = (ClassPathXmlApplicationContext) applicationContext;
           Map<String, Object> serviceBeanMap = applicationContext.getBeansWithAnnotation(RpcService.class);
           applicationContext.getBean("userService");
     }

}
通过创建一个实例,用于存储当前初始化的Spring上下文,可以在后续的应用场景中调用。
@Component
public class ApplicationContextHelper implements ApplicationContextAware {
     private static ApplicationContext applicationContext;
     @Override
     public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
           ApplicationContextHelper.applicationContext = applicationContext;
     }

     public static <T> T getBean(Class<T> clazz){
           return applicationContext.getBean(clazz);
     }
}

2.初始化Spring上下文
new ClassPathXmlApplicationContext("server-spring.xml");

主要有以下接口定义
EnvironmentAware
EmbeddedValueResolverAware
ResourceLoaderAware
ApplicationEventPublisherAware
MessageSourceAware
ApplicationContextAware

ApplicationContextAware的应用
ApplicationContextAware的最本质的应用就是:对当前bean传入对应的Spring上下文。

1.保存Spring上下文
例如上文中的ApplicationContextHelper,专门创建一个Bean,用于维护Spring ApplicationContext。并且可以将ApplicationContextHelper通过@Resource的形式注入到其他组件中。这样相当于为所有的Bean提供可一个操作Spring上下文的工具类

2.监听上下文启动,并完成相关操作
通过在实例化到时候,通过上下文调用setApplicationContext方法,然后完成一些自定义的操作。例如加载某些特殊的实例,对bean进行操作等。

ApplicationContextAware源码
 
在AbstractApplicationContext的refresh方法中的prepareBeanFactory(beanFactory);方法。添加了ApplicationContextAwareProcessor处理器,
ApplicationContextAwareProcessor是继承了BeanPostProcessor接口。在bean实例化的时候,也就是Spring激活bean的init-method方法的前后,会调用BeanPostProcessor的postProcessBeforeInitialization方法和postProcessAfterInitialization。
在ApplicationContextAwareProcessor我们同样关心这两个方法。在postProcessBeforeInitialization方法中,可以看到会调用invokeAwareInterfaces方法,其中判断了当前初始化bean时候继承了对应的Aware,如果是则调用对应的set方法,传入对应的资源。

所有的BeanPostProcessor都将在AbstractAutowireCapableBeanFactory类的initializeBean方法中,通过调用applyBeanPostProcessorsBeforeInitialization方法完成所有实现BeanPostProcessor接口的postProcessBeforeInitialization的调用。

AbstractApplicationContext.prepareBeanFactory
protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) {
     // Tell the internal bean factory to use the context's class loader etc.
     beanFactory.setBeanClassLoader(getClassLoader());
     beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader()));
     beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment()));

     // Configure the bean factory with context callbacks.
     beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));
     beanFactory.ignoreDependencyInterface(ResourceLoaderAware.class);
     beanFactory.ignoreDependencyInterface(ApplicationEventPublisherAware.class);
     beanFactory.ignoreDependencyInterface(MessageSourceAware.class);
     beanFactory.ignoreDependencyInterface(ApplicationContextAware.class);
     beanFactory.ignoreDependencyInterface(EnvironmentAware.class);

     // BeanFactory interface not registered as resolvable type in a plain factory.
     // MessageSource registered (and found for autowiring) as a bean.
     beanFactory.registerResolvableDependency(BeanFactory.class, beanFactory);
     beanFactory.registerResolvableDependency(ResourceLoader.class, this);
     beanFactory.registerResolvableDependency(ApplicationEventPublisher.class, this);
     beanFactory.registerResolvableDependency(ApplicationContext.class, this);

     .....
     ...
     ..
}

 

ApplicationContextAwareProcessor.postProcessBeforeInitialization
@Override
public Object postProcessBeforeInitialization(final Object bean, String beanName) throws BeansException {
     AccessControlContext acc = null;

     if (System.getSecurityManager() != null &&
                (bean instanceof EnvironmentAware || bean instanceof EmbeddedValueResolverAware ||
                           bean instanceof ResourceLoaderAware || bean instanceof ApplicationEventPublisherAware ||
                           bean instanceof MessageSourceAware || bean instanceof ApplicationContextAware)) {
           acc = this.applicationContext.getBeanFactory().getAccessControlContext();
     }

     if (acc != null) {
           AccessController.doPrivileged(new PrivilegedAction<Object>() {
                @Override
                public Object run() {
                     invokeAwareInterfaces(bean);
                     return null;
                }
           }, acc);
     }else {
           invokeAwareInterfaces(bean);
     }

     return bean;
}

private void invokeAwareInterfaces(Object bean) {
     if (bean instanceof Aware) {
           if (bean instanceof EnvironmentAware) {
                ((EnvironmentAware) bean).setEnvironment(this.applicationContext.getEnvironment());
           }
           if (bean instanceof EmbeddedValueResolverAware) {
                ((EmbeddedValueResolverAware) bean).setEmbeddedValueResolver(
                           new EmbeddedValueResolver(this.applicationContext.getBeanFactory()));
           }
           if (bean instanceof ResourceLoaderAware) {
                ((ResourceLoaderAware) bean).setResourceLoader(this.applicationContext);
           }
           if (bean instanceof ApplicationEventPublisherAware) {
                ((ApplicationEventPublisherAware) bean).setApplicationEventPublisher(this.applicationContext);
           }
           if (bean instanceof MessageSourceAware) {
                ((MessageSourceAware) bean).setMessageSource(this.applicationContext);
           }
           if (bean instanceof ApplicationContextAware) {
                ((ApplicationContextAware) bean).setApplicationContext(this.applicationContext);
           }
     }
}

@Override
public Object postProcessAfterInitialization(Object bean, String beanName) {
     return bean;
}

 

其他Web扩展
在web应用中,还可以添加ServletContextAware,ServletConfigAware。
在web项目中,Spring容器的加载是通常是通过XmlWebApplicationContext进行的。

它的父类AbstractRefreshableWebApplicationContext,在postProcessBeanFactory方法中进行了如下操作(postProcessBeanFactory方法被AbstractApplicationContext的refresh方法调用)

AbstractRefreshableWebApplicationContext.postProcessBeanFactory
@Override
protected void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {
     beanFactory.addBeanPostProcessor(new ServletContextAwareProcessor(this.servletContext, this.servletConfig));
     beanFactory.ignoreDependencyInterface(ServletContextAware.class);
     beanFactory.ignoreDependencyInterface(ServletConfigAware.class);

     WebApplicationContextUtils.registerWebApplicationScopes(beanFactory, this.servletContext);
     WebApplicationContextUtils.registerEnvironmentBeans(beanFactory, this.servletContext, this.servletConfig);
}

ServletContextAwareProcessor.postProcessBeforeInitialization
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
     if (getServletContext() != null && bean instanceof ServletContextAware) {
           ((ServletContextAware) bean).setServletContext(getServletContext());
     }
     if (getServletConfig() != null && bean instanceof ServletConfigAware) {
           ((ServletConfigAware) bean).setServletConfig(getServletConfig());
     }
     return bean;
}
---------------------
作者:强迫症患者m
来源:CSDN
原文:https://blog.csdn.net/mdq11111/article/details/79050280
版权声明:本文为博主原创文章,转载请附上博文链接!

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



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

相关文章

Java实现检查多个时间段是否有重合

《Java实现检查多个时间段是否有重合》这篇文章主要为大家详细介绍了如何使用Java实现检查多个时间段是否有重合,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录流程概述步骤详解China编程步骤1:定义时间段类步骤2:添加时间段步骤3:检查时间段是否有重合步骤4:输出结果示例代码结语作

Java中String字符串使用避坑指南

《Java中String字符串使用避坑指南》Java中的String字符串是我们日常编程中用得最多的类之一,看似简单的String使用,却隐藏着不少“坑”,如果不注意,可能会导致性能问题、意外的错误容... 目录8个避坑点如下:1. 字符串的不可变性:每次修改都创建新对象2. 使用 == 比较字符串,陷阱满

Java判断多个时间段是否重合的方法小结

《Java判断多个时间段是否重合的方法小结》这篇文章主要为大家详细介绍了Java中判断多个时间段是否重合的方法,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录判断多个时间段是否有间隔判断时间段集合是否与某时间段重合判断多个时间段是否有间隔实体类内容public class D

IDEA编译报错“java: 常量字符串过长”的原因及解决方法

《IDEA编译报错“java:常量字符串过长”的原因及解决方法》今天在开发过程中,由于尝试将一个文件的Base64字符串设置为常量,结果导致IDEA编译的时候出现了如下报错java:常量字符串过长,... 目录一、问题描述二、问题原因2.1 理论角度2.2 源码角度三、解决方案解决方案①:StringBui

Java覆盖第三方jar包中的某一个类的实现方法

《Java覆盖第三方jar包中的某一个类的实现方法》在我们日常的开发中,经常需要使用第三方的jar包,有时候我们会发现第三方的jar包中的某一个类有问题,或者我们需要定制化修改其中的逻辑,那么应该如何... 目录一、需求描述二、示例描述三、操作步骤四、验证结果五、实现原理一、需求描述需求描述如下:需要在

Java中ArrayList和LinkedList有什么区别举例详解

《Java中ArrayList和LinkedList有什么区别举例详解》:本文主要介绍Java中ArrayList和LinkedList区别的相关资料,包括数据结构特性、核心操作性能、内存与GC影... 目录一、底层数据结构二、核心操作性能对比三、内存与 GC 影响四、扩容机制五、线程安全与并发方案六、工程

JavaScript中的reduce方法执行过程、使用场景及进阶用法

《JavaScript中的reduce方法执行过程、使用场景及进阶用法》:本文主要介绍JavaScript中的reduce方法执行过程、使用场景及进阶用法的相关资料,reduce是JavaScri... 目录1. 什么是reduce2. reduce语法2.1 语法2.2 参数说明3. reduce执行过程

如何使用Java实现请求deepseek

《如何使用Java实现请求deepseek》这篇文章主要为大家详细介绍了如何使用Java实现请求deepseek功能,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录1.deepseek的api创建2.Java实现请求deepseek2.1 pom文件2.2 json转化文件2.2

Java调用DeepSeek API的最佳实践及详细代码示例

《Java调用DeepSeekAPI的最佳实践及详细代码示例》:本文主要介绍如何使用Java调用DeepSeekAPI,包括获取API密钥、添加HTTP客户端依赖、创建HTTP请求、处理响应、... 目录1. 获取API密钥2. 添加HTTP客户端依赖3. 创建HTTP请求4. 处理响应5. 错误处理6.

Spring AI集成DeepSeek的详细步骤

《SpringAI集成DeepSeek的详细步骤》DeepSeek作为一款卓越的国产AI模型,越来越多的公司考虑在自己的应用中集成,对于Java应用来说,我们可以借助SpringAI集成DeepSe... 目录DeepSeek 介绍Spring AI 是什么?1、环境准备2、构建项目2.1、pom依赖2.2