Spring IOC容器和获取组件对象源码分析
打上断点进行调试
1 第一步是进入了ClassPathXmlApplicationContext调用其构造参数,其中配置文件的内容被解析成了数组
public ClassPathXmlApplicationContext(String configLocation) throws BeansException {this(new String[]{configLocation}, true, (ApplicationContext)null);}//上面的构造器内部调用的就是以下这个构造器
public ClassPathXmlApplicationContext(String[] configLocations, boolean refresh, @Nullable ApplicationContext parent) throws BeansException {super(parent);//自动配置文件所在的位置this.setConfigLocations(configLocations);if (refresh) {//此处所有的单实例bean创建完成,我们继续进入refresh方法内进行研究this.refresh();}
}
//3 第三步用来分析refresh(),此处所有的单实例bean创建完成
public void refresh() throws BeansException, IllegalStateException {
//this.startupShutdownMonitors是类中定义的一个用专门于同步的锁对象,同步多线程ioc容器的创建于销毁,即保证多线程下ioc只能被创建一次synchronized(this.startupShutdownMonitor) {
//刷新容器this.prepareRefresh();//通过解析spring.xml配置文件创建了beanFactory对象,它的内部获取了组件的基本信息并保存在了beanDefinitionMap中,通过它来创建组件对象,解析的原理主要就是通过反射ConfigurableListableBeanFactory beanFactory = this.obtainFreshBeanFactory();
//此时bean工厂已准备好,配置文件已被解析this.prepareBeanFactory(beanFactory);try {//加载bean工厂的后置处理器this.postProcessBeanFactory(beanFactory);//执行beanFactory的后置处理器this.invokeBeanFactoryPostProcessors(beanFactory);//注册bean工厂的后置处理器this.registerBeanPostProcessors(beanFactory);//用于支持国际化功能this.initMessageSource();//初始化容器多事件转发器this.initApplicationEventMulticaster();//留给子类(开发中)自己写容器时进行扩展实现this.onRefresh();//注册spring内部监听器this.registerListeners();//完成beanFactory的初始化 => 所有单实例对象加载完毕,我们需要对该方法进一步研究this.finishBeanFactoryInitialization(beanFactory);this.finishRefresh();} catch (BeansException var9) {......} finally {......}}
}
该方法可以理解为初始化所有单实例bean
protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {if (beanFactory.containsBean("conversionService") && beanFactory.isTypeMatch("conversionService", ConversionService.class)) {beanFactory.setConversionService((ConversionService)beanFactory.getBean("conversionService", ConversionService.class));}if (!beanFactory.hasEmbeddedValueResolver()) {beanFactory.addEmbeddedValueResolver((strVal) -> {return this.getEnvironment().resolvePlaceholders(strVal);});}String[] weaverAwareNames = beanFactory.getBeanNamesForType(LoadTimeWeaverAware.class, false, false);String[] var3 = weaverAwareNames;int var4 = weaverAwareNames.length;for(int var5 = 0; var5 < var4; ++var5) {String weaverAwareName = var3[var5];this.getBean(weaverAwareName);}beanFactory.setTempClassLoader((ClassLoader)null);beanFactory.freezeConfiguration();//主要研究这个放beanFactory.preInstantiateSingletons();
}
只要不是抽象bean,不是多实例bean,不是懒加载,就通过this.getBean(beanName);
获取对象
public void preInstantiateSingletons() throws BeansException {
//日志处理if (this.logger.isTraceEnabled()) {this.logger.trace("Pre-instantiating singletons in " + this);}//拿到所有bean组件的名字放到list中然后继续遍历,其中beanDefinitionNames中具有容器中全部组件的详细信息,如名字、作用域、是否抽象....List<String> beanNames = new ArrayList(this.beanDefinitionNames);Iterator var2 = beanNames.iterator();//顺序遍历bean组件,所以实际开发中bean对象的创建顺序与它们在容器中的顺序一致while(true) {String beanName;Object bean;do {while(true) {RootBeanDefinition bd;do {do {do {if (!var2.hasNext()) {var2 = beanNames.iterator();while(var2.hasNext()) {beanName = (String)var2.next();Object singletonInstance = this.getSingleton(beanName);if (singletonInstance instanceof SmartInitializingSingleton) {SmartInitializingSingleton smartSingleton = (SmartInitializingSingleton)singletonInstance;if (System.getSecurityManager() != null) {AccessController.doPrivileged(() -> {smartSingleton.afterSingletonsInstantiated();return null;}, this.getAccessControlContext());} else {smartSingleton.afterSingletonsInstantiated();}}}return;}beanName = (String)var2.next();bd = this.getMergedLocalBeanDefinition(beanName);//创建条件1:组件不能是抽象的} while(bd.isAbstract());//创建条件1:组件不能是抽象的} while(!bd.isSingleton());} while(bd.isLazyInit());if (this.isFactoryBean(beanName)) {bean = this.getBean("&" + beanName);break;}this.getBean(beanName);}/*FactoryBean是Spring中工厂模式应用案例,继承FactoryBean的pojo类返回的不是该类的pojo对象,而是pojo内部重写的FactoryBean的getObject方法中返回的对象*/} while(!(bean instanceof FactoryBean));FactoryBean<?> factory = (FactoryBean)bean;boolean isEagerInit;if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) {SmartFactoryBean var10000 = (SmartFactoryBean)factory;((SmartFactoryBean)factory).getClass();isEagerInit = (Boolean)AccessController.doPrivileged(var10000::isEagerInit, this.getAccessControlContext());} else {isEagerInit = factory instanceof SmartFactoryBean && ((SmartFactoryBean)factory).isEagerInit();}if (isEagerInit) {this.getBean(beanName);}}
}
//调用getBean实际就是调用AbstractBeanFactory子类的doGetBean方法
public Object getBean(String name) throws BeansException {return this.doGetBean(name, (Class)null, (Object[])null, false);
}
protected <T> T doGetBean(String name, @Nullable Class<T> requiredType, @Nullable Object[] args, boolean typeCheckOnly) throws BeansException {
//获取组件名String beanName = this.transformedBeanName(name);
/*
先从已注册的单实例bean中,也就是单例池中,查看有无这个组件,没有就先创建,后续再次创建直接从单例池中拿即可
*/Object sharedInstance = this.getSingleton(beanName);Object bean;bean = this.getObjectForBeanInstance(sharedInstance, name, beanName, (RootBeanDefinition)null);} else {if (this.isPrototypeCurrentlyInCreation(beanName)) {throw new BeanCurrentlyInCreationException(beanName);}BeanFactory parentBeanFactory = this.getParentBeanFactory();if (parentBeanFactory != null && !this.containsBeanDefinition(beanName)) {String nameToLookup = this.originalBeanName(name);if (parentBeanFactory instanceof AbstractBeanFactory) {return ((AbstractBeanFactory)parentBeanFactory).doGetBean(nameToLookup, requiredType, args, typeCheckOnly);}if (args != null) {return parentBeanFactory.getBean(nameToLookup, args);}if (requiredType != null) {return parentBeanFactory.getBean(nameToLookup, requiredType);}return parentBeanFactory.getBean(nameToLookup);}if (!typeCheckOnly) {
//标记bean已经被创建this.markBeanAsCreated(beanName);}try {RootBeanDefinition mbd = this.getMergedLocalBeanDefinition(beanName);this.checkMergedBeanDefinition(mbd, beanName, args);
//拿到这个bean的依赖bean并先于该bean创建这个组件String[] dependsOn = mbd.getDependsOn();String[] var11;
//循环创建这个bean所依赖的组件对象if (dependsOn != null) {var11 = dependsOn;int var12 = dependsOn.length;for(int var13 = 0; var13 < var12; ++var13) {String dep = var11[var13];if (this.isDependent(beanName, dep)) {throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Circular depends-on relationship between '" + beanName + "' and '" + dep + "'");}this.registerDependentBean(dep, beanName);try {this.getBean(dep);} catch (NoSuchBeanDefinitionException var24) {throw new BeanCreationException(mbd.getResourceDescription(), beanName, "'" + beanName + "' depends on missing bean '" + dep + "'", var24);}}}//如果是单例模式if (mbd.isSingleton()) {
//创建单例beansharedInstance = this.getSingleton(beanName, () -> {try {return this.createBean(beanName, mbd, args);} catch (BeansException var5) {this.destroySingleton(beanName);throw var5;}});bean = this.getObjectForBeanInstance(sharedInstance, name, beanName, mbd);}
//真正的创建组件对象的方法
public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {Assert.notNull(beanName, "Bean name must not be null");synchronized(this.singletonObjects) {Object singletonObject = this.singletonObjects.get(beanName);if (singletonObject == null) {if (this.singletonsCurrentlyInDestruction) {throw new BeanCreationNotAllowedException(beanName, "Singleton bean creation not allowed while singletons of this factory are in destruction (Do not request a bean from a BeanFactory in a destroy method implementation!)");}if (this.logger.isDebugEnabled()) {this.logger.debug("Creating shared instance of singleton bean '" + beanName + "'");}this.beforeSingletonCreation(beanName);boolean newSingleton = false;boolean recordSuppressedExceptions = this.suppressedExceptions == null;if (recordSuppressedExceptions) {this.suppressedExceptions = new LinkedHashSet();}try {
//此处获取到单例bean对象singletonObject = singletonFactory.getObject();newSingleton = true;} catch (IllegalStateException var16) {singletonObject = this.singletonObjects.get(beanName);if (singletonObject == null) {throw var16;}} catch (BeanCreationException var17) {BeanCreationException ex = var17;if (recordSuppressedExceptions) {Iterator var8 = this.suppressedExceptions.iterator();while(var8.hasNext()) {Exception suppressedException = (Exception)var8.next();ex.addRelatedCause(suppressedException);}}throw ex;} finally {if (recordSuppressedExceptions) {this.suppressedExceptions = null;}this.afterSingletonCreation(beanName);}//如果是新建的单例对象,就将其加入到单例池中if (newSingleton) {this.addSingleton(beanName, singletonObject);}}return singletonObject;}
}
Spring IOC容器和获取组件对象源码分析相关推荐
- Spring IOC和Bean生命周期以及源码分析
这篇文章主要讲解 IOC 容器的创建过程,让大家对整体有一个全局的认识,文章目录如图: 1. 基础知识 1.1 什么是 Spring IOC ? IOC 不是一种技术,只是一种思想,一个重要的面向对象 ...
- java 从一个容器获取对象,如何从 Spring IoC 容器中获取对象?
前面几篇文章主要分析了 Spring IoC 容器如何初始化,以及解析和注册我们定义的 bean 信息. 其中,「Spring 中的 IoC 容器」对 Spring 中的容器做了一个概述,「Sprin ...
- java使用websocket,并且获取HttpSession,源码分析
一:本文使用范围 此文不仅仅局限于spring boot,普通的spring工程,甚至是servlet工程,都是一样的,只不过配置一些监听器的方法不同而已. 本文经过作者实践,确认完美运行. 二:Sp ...
- java 获取httpsession_java使用websocket,并且获取HttpSession,源码分析
转载请在页首注明作者与出处 http://www.cnblogs.com/zhuxiaojie/p/6238826.html 一:本文使用范围 此文不仅仅局限于spring boot,普通的sprin ...
- 《微信小程序-进阶篇》Lin-ui组件库源码分析-列表组件List(一)
大家好,这是小程序系列的第二十篇文章,在这一个阶段,我们的目标是 由简单入手,逐渐的可以较为深入的了解组件化开发,从本文开始,将记录分享lin-ui的源码分析,期望通过对lin-ui源码的学习能加深组 ...
- Spring自定义注解驱动开发使用及源码分析
目录 前言 注解驱动开发使用 需求 代码实现 测试效果 源码分析 BeanDefinitionRegistryPostProcessor接口 解析BeanDefinition 处理Bean上配置的注解 ...
- 动态代理最全详解系列[2]-Proxy生成代理类对象源码分析
之前我们通过JDK中的Proxy实现了动态代理,Proxy用起来是比较简便的,但理解起来不是那么清晰,是因为我们并没有看见代理类是怎么生成的,代理类怎么调用的被代理类方法,所以下面我们进入源码看一 ...
- 聊聊Spring中的数据绑定 --- DataBinder本尊(源码分析)
每篇一句 唯有热爱和坚持,才能让你在程序人生中屹立不倒,切忌跟风什么语言或就学什么去~ 相关阅读 [小家Spring]聊聊Spring中的数据转换:Converter.ConversionServic ...
- 聊聊Spring中的数据绑定 --- DataBinder本尊(源码分析)【享学Spring】
每篇一句 唯有热爱和坚持,才能让你在程序人生中屹立不倒,切忌跟风什么语言或就学什么去~ 前言 数据绑定 这个概念在任何一个成型的框架中都是特别重要的(尤其是web框架),它能让框架更多的自动化,更好容 ...
最新文章
- 横向ListView(一) ——开篇,基础逻辑实现
- 斐波那契数列性质【记住】
- pandas移除dataframe字符串数据列中的后N个字符(remove the last n characters from values from column of dataframe)
- IntelliJ IDEA Groovy(转)
- 西北工业大学附属中学2019届高考毕业生去向,其中北大清华88人
- linux sed给空文件首行插入_Sed命令高级功能,学好了工作不愁
- XCTF WEB view_source
- 用栈和递归求解迷宫问题
- C++工作笔记-对二级指针的进一步理解(获取调用者的地址)
- Spark API编程动手实战-08-基于IDEA使用Spark API开发Spark程序-01
- 疑似华为P50系列7月29日发布:麒麟9000旗舰芯片加持
- mysql checkpoint_MySQL checkpoint深入分析
- 众觅,让支付宝『到位』全国到位
- STM32单片机开发板 定制
- 响铃:金蝶的SaaS第一能保持多久?
- ctf镜子里面的世界_一个小编姐姐的CTF入坑之旅
- Python爬虫爬取古诗文网站项目分享
- python openpyxl操作Excel表格
- STM32-(ADC,DMA,重映射)
- Flutter开发日志——初生牛犊