引言

Spring中提供了各种Aware接口,方便从上下文中获取当前的运行环境,比较常见的几个子接口有:BeanFactoryAware,BeanNameAware,ApplicationContextAware,EnvironmentAware,BeanClassLoaderAware等,这些Aware的作用都可以从命名得知

Aware处理

其中BeanNameAwareBeanClassLoaderAwareBeanFactoryAware这三个是直接在bean的初始化之前就处理了的,具体代码在AbstractAutowireCapableBeanFactory.initializeBean方法中:

protected Object initializeBean(String beanName, Object bean, RootBeanDefinition mbd) {
// 判断对象实现的接口类型,处理特定的三种接口类型:BeanNameAware、BeanClassLoaderAware和BeanFactoryAware。
if (bean instanceof BeanNameAware) {
((BeanNameAware) bean).setBeanName(beanName);
} if (bean instanceof BeanClassLoaderAware) {
((BeanClassLoaderAware) bean).setBeanClassLoader(getBeanClassLoader());
} if (bean instanceof BeanFactoryAware) {
((BeanFactoryAware) bean).setBeanFactory(this);
}
// 开始Bean初始化前处理、初始化、初始化后处理
Object wrappedBean = bean;
if (mbd == null || !mbd.isSynthetic()) {
wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
} try {
invokeInitMethods(beanName, wrappedBean, mbd);
}
catch (Throwable ex) {
throw new BeanCreationException(
(mbd != null ? mbd.getResourceDescription() : null),
beanName, "Invocation of init method failed", ex);
} if (mbd == null || !mbd.isSynthetic()) {
wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
}
return wrappedBean;
}

除了这三种之外的那些Aware接口的实现就不太一样了,它们都是利用BeanPostProcessor接口完成的,关于BeanPostProcessor接口的原理可以这篇文章:Spring扩展点之BeanPostProcessor

ApplicationContextAware就是利用ApplicationContextAwareProcessor实现的:

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((PrivilegedAction<Object>) () -> {
//具体实现
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(this.embeddedValueResolver);
}
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);
}
}
}

ApplicationContextAwareProcessor的注册奥秘在AbstractApplicationContext.prepareBeanFactory方法中:

beanFactory.setBeanClassLoader(getClassLoader());
beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this));
beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));
beanFactory.ignoreDependencyInterface(ResourceLoaderAware.class);
beanFactory.ignoreDependencyInterface(ApplicationEventPublisherAware.class);
beanFactory.ignoreDependencyInterface(MessageSourceAware.class);
beanFactory.ignoreDependencyInterface(ApplicationContextAware.class);

Spring扩展点之Aware接口族的更多相关文章

  1. Spring扩展点之FactoryBean接口

    前言 首先看一下接口定义 public interface FactoryBean<T> { /** * 返回对象实例 */ @Nullable T getObject() throws ...

  2. spring源码:Aware接口(li)

    一.spring容器中的aware接口介绍 Spring中提供了各种Aware接口,比较常见的如BeanFactoryAware,BeanNameAware,ApplicationContextAwa ...

  3. spring源码:Aware接口

    一.spring容器中的aware接口介绍 Spring中提供了各种Aware接口,比较常见的如BeanFactoryAware,BeanNameAware,ApplicationContextAwa ...

  4. Spring扩展点-v5.3.9

    Spring 扩展点 **本人博客网站 **IT小神 www.itxiaoshen.com 官网地址****:https://spring.io/projects/spring-framework T ...

  5. Spring扩展之五:Aware接口等

    ApplicationContextAwareProcessor 1.介绍 ApplicationContextAwareProcessor是一个Spring内部工具,它实现了接口BeanPostPr ...

  6. Spring扩展点之BeanPostProcessor

    前言 BeanPostProcessor接口是Spring中一个非常重要的接口,它的接口定义如下 public interface BeanPostProcessor { Object postPro ...

  7. Spring扩展点之BeanFactoryPostProcessor

    前言 BeanFactoryPostProcessor接口是Spring中一个非常重要的接口,它的接口定义如下 public interface BeanFactoryPostProcessor { ...

  8. 手写Spring,定义标记类型Aware接口,实现感知容器对象

    作者:小傅哥 博客:https://bugstack.cn 沉淀.分享.成长,让自己和他人都能有所收获! 一.前言 同事写的代码,我竟丝毫看不懂! 大佬的代码,就像 "赖蛤蟆泡青蛙,张的丑玩 ...

  9. spring扩展点之PropertyPlaceholderConfigurer

    原理机制讲解 https://leokongwq.github.io/2016/12/28/spring-PropertyPlaceholderConfigurer.html 使用时多个配置讲解 ht ...

随机推荐

  1. python 一些程序规范(跨目录调用文件)

    文档内容学习于 http://www.cnblogs.com/xiaozhiqi/ 参考: https://www.cnblogs.com/monologuesmw/p/9490093.html 软件 ...

  2. 莫烦TensorFlow_11 MNIST优化使用CNN

    import tensorflow as tf from tensorflow.examples.tutorials.mnist import input_data #number 1 to 10 d ...

  3. [笔记] nice-upload 与 nice-static-server

    1.request 支持流模式,管道流pipe,抓取图片并保存就很方便了 request('https://s.gravatar.com/avatar/184a1f14c759795b94ae1d01 ...

  4. vue项目的安装与启动

      第一步:安装Node 检测Node是否安装成功 node -v 第二步:安装vue-cli     命令:npm install vue-cli -g 第三步:搭建项目命令 vue init we ...

  5. 后来,我发现,要想用好WIMBuilder2你必须具有以下能力:

    后来,我发现,要想用好WIMBuilder2你必须具有以下能力:1.一定的中文语言阅读能力,两个帖子1500楼层中主要的功能要弄明白,包括wimbuilder2的架构.补丁的制作.2.一定的英文语言阅 ...

  6. Linux性能优化实战学习笔记:第九讲

    一.中断的魅力 1.中断在生活的魅力 比如你订了一份外卖,但是不确定外卖什么时候送到,也没有别的方法了解外卖的进度,但是,配送员送外卖是不等人的,到了你这儿没人取的话,就直接走人了.所以你指能苦苦等着 ...

  7. [LeetCode] 28. Implement strStr() 实现strStr()函数

    Implement strStr(). Return the index of the first occurrence of needle in haystack, or -1 if needle ...

  8. c++性能测试工具:计算时间复杂度

    有时候除了测量算法的具体性能指数,我们也会希望测试出算法的时间复杂度,以便我们对待测试的算法的性能有一个更加直观的了解. 测量时间复杂度 google benchmark已经为我们提供了类似的功能,而 ...

  9. Java代码中对IP进行白名单验证

    来自:https://www.cnblogs.com/shinubi/p/6723003.html public class ipUtil { // IP的正则,这个正则不能验证第一组数字为0的情况 ...

  10. Shell脚本——显示系统上的登录用户数

    写一个脚本showlogged.sh,其用法格式为: showlogged.sh -v -c -h|--help 其中,-h选项只能单独使用,用于显示帮助信息:-c选项时,显示当前系统上登录的所有用户 ...