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中流式并行操作parallelStream的原理和使用方法

《Java中流式并行操作parallelStream的原理和使用方法》本文详细介绍了Java中的并行流(parallelStream)的原理、正确使用方法以及在实际业务中的应用案例,并指出在使用并行流... 目录Java中流式并行操作parallelStream0. 问题的产生1. 什么是parallelS

Java中Redisson 的原理深度解析

《Java中Redisson的原理深度解析》Redisson是一个高性能的Redis客户端,它通过将Redis数据结构映射为Java对象和分布式对象,实现了在Java应用中方便地使用Redis,本文... 目录前言一、核心设计理念二、核心架构与通信层1. 基于 Netty 的异步非阻塞通信2. 编解码器三、

SpringBoot基于注解实现数据库字段回填的完整方案

《SpringBoot基于注解实现数据库字段回填的完整方案》这篇文章主要为大家详细介绍了SpringBoot如何基于注解实现数据库字段回填的相关方法,文中的示例代码讲解详细,感兴趣的小伙伴可以了解... 目录数据库表pom.XMLRelationFieldRelationFieldMapping基础的一些代

一篇文章彻底搞懂macOS如何决定java环境

《一篇文章彻底搞懂macOS如何决定java环境》MacOS作为一个功能强大的操作系统,为开发者提供了丰富的开发工具和框架,下面:本文主要介绍macOS如何决定java环境的相关资料,文中通过代码... 目录方法一:使用 which命令方法二:使用 Java_home工具(Apple 官方推荐)那问题来了,

Java HashMap的底层实现原理深度解析

《JavaHashMap的底层实现原理深度解析》HashMap基于数组+链表+红黑树结构,通过哈希算法和扩容机制优化性能,负载因子与树化阈值平衡效率,是Java开发必备的高效数据结构,本文给大家介绍... 目录一、概述:HashMap的宏观结构二、核心数据结构解析1. 数组(桶数组)2. 链表节点(Node

Java AOP面向切面编程的概念和实现方式

《JavaAOP面向切面编程的概念和实现方式》AOP是面向切面编程,通过动态代理将横切关注点(如日志、事务)与核心业务逻辑分离,提升代码复用性和可维护性,本文给大家介绍JavaAOP面向切面编程的概... 目录一、AOP 是什么?二、AOP 的核心概念与实现方式核心概念实现方式三、Spring AOP 的关

详解SpringBoot+Ehcache使用示例

《详解SpringBoot+Ehcache使用示例》本文介绍了SpringBoot中配置Ehcache、自定义get/set方式,并实际使用缓存的过程,文中通过示例代码介绍的非常详细,对大家的学习或者... 目录摘要概念内存与磁盘持久化存储:配置灵活性:编码示例引入依赖:配置ehcache.XML文件:配置

Java 虚拟线程的创建与使用深度解析

《Java虚拟线程的创建与使用深度解析》虚拟线程是Java19中以预览特性形式引入,Java21起正式发布的轻量级线程,本文给大家介绍Java虚拟线程的创建与使用,感兴趣的朋友一起看看吧... 目录一、虚拟线程简介1.1 什么是虚拟线程?1.2 为什么需要虚拟线程?二、虚拟线程与平台线程对比代码对比示例:三

Java中的.close()举例详解

《Java中的.close()举例详解》.close()方法只适用于通过window.open()打开的弹出窗口,对于浏览器的主窗口,如果没有得到用户允许是不能关闭的,:本文主要介绍Java中的.... 目录当你遇到以下三种情况时,一定要记得使用 .close():用法作用举例如何判断代码中的 input

深入理解Mysql OnlineDDL的算法

《深入理解MysqlOnlineDDL的算法》本文主要介绍了讲解MysqlOnlineDDL的算法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小... 目录一、Online DDL 是什么?二、Online DDL 的三种主要算法2.1COPY(复制法)