本文共 4223 字,大约阅读时间需要 14 分钟。
1、从资源读取bean的创建信息(BeanDefinition)
读取spring的xml配置文件,得到bean的创建信息BeanDefinition,最终bean的信息保存在DefaultListableBeanFactory.beanDefinitionMap,该类提供对象仓储88服务
private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<>(256);
2、解析bean信息得到bean对象,扫描bean信息,循环依赖,注入属性,保存到内存集合
单例模式对象,从缓存读取singletonObjects,singletonFactories,earlySingletonObjects
非单例模式,每次创建新对象,工厂方法或者构造函数创建。
3、用户得到bean对象
通过context或factory对象得到
.
1.1、jvm运行jar包,加载jar里的类信息到方法区,
1.2、用类路径资源加载对象(ClassPathResource),获得当前类信息下的附属配置文件, 1.3、读取文件构建资源对象 1.4、用资源创建一个xmlbean工厂对象(XmlBeanFactory)1.4.1、XmlBeanFactory 继承DefaultListableBeanFactory XmlBeanFactory 依赖XmlBeanDefinitionReader
1.4.2、DefaultListableBeanFactory 是spring注册加载bean的默认实现 和xmlbeanFactory主要区别是用到XmlBeanDefinitionReader DefaultListableBeanFactory 继承自 AbstractAutowireCapableBeanFactory 实现了 ConfigurableListableBeanFactory BeanDefinitionRegistry 和 Serializable 接口
1.5、XmlBeanFactory解析资源,得到bean的创建信息,
.
2.1、转换对应的beanName,(从beanName,别名, FactoryBean)
2.2、尝试从缓存中加载单例,(bean缓存,singletonFactories ,循环依赖先暴露ObjectFactory)如果从中得到了bean的原始状态,则进行bean实例化
(什么是原始状态object,有可能是bean对象,匜有可能是继承了FactoryBean的工厂对象,通过判断类型instanceof FactoryBean做处理,如果是工厂创建的bean有独立的缓存)
2.3、如果加载不到缓存,先判断是否是原型循环依赖(isPrototypeCurrentlyInCreation)是的话抛异常(BeanCurrentlyInCreationException)
2.4、如果该beanName在当前beanFactory里找不到(beanDefinitionMap (XML配置文件)里没有该bean),且有父级beanFactory,就调用父级的getBean(检查AbstractBeanFactory,BeanFactory,构造参数,指定返回类型,分情况处理) 2.5、如果beanName在当前beanFactory里找得到,继续按主线流程获得bean 2.6、进行depends-on标签判断,如果有强依赖关系,比如分析文件的bean只能在载入文件的bean后面创建,则先创建depends-on标签指定的bean, 例子参考 2.7、前置条件走完了,开始创建bean了,根据作用域分为单例模式,原型模式,其他三种情况 2.8、单例模式创建bean,从缓存读取,缓存没有则调用createBean创建,最后调 2.9、原型模式创建bean 2.10、其他自定义情况创建bean(request、session、global session) 预先实现自定义的Scope保持在this.scopes缓存, 把本对象的getbean相关方法封装定义成一个ObjectFactory<?> 根据名称从.scopes缓存找到对应的Scope,调用Scope.get(beanName,ObjectFactory<?>)得到bean.
1)用于保存BeanName和创建bean实例之间的关系
private final Map<String, Object>singletonObjects = new ConcurrentHashMap<>(256);
2)用于保存BeanName和创建bean的工厂之间的关系
private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<>(16);
3)也是保存BeanName和创建bean实例之间的关系,与singletonObjects不同之处在于,当一个单例bean被放在里面后那么bean还在创建过程中,就可以通过getBean方法获取到了,其目的是用来循环检测引用
private final Map<String, Object> earlySingletonObjects = new HashMap<>(16);
4)用来保存当前所有已注册的bean名称
private final Set registeredSingletons = new LinkedHashSet<>(256);
.
1、检查缓存是否已经加载过;
2、如果加载过直接返回缓存中的 bean;如果没有加载,则记录 beanName 的正在加载状态,用于循环依赖检查 ; 3、加载单例前记录加载状态; 4、当 bean 加载结束后需要移除缓存中对该 bean 的正在加载状态的记录。 5、将结果记录至缓存并删除加载 bean 过程中所记录的各种辅助状态;循环依赖
构造器循环依赖,setter循环依赖,构造器和setter混合循环依赖,第一个是构造器则异常 Spring首先从一级缓存 singletonObjects 中获取,如果获取不到,并且对象正在创建中,就再从二级缓存 earlySingletonObjects 中获取。如果还是获取不到且允许 singletonFactories 通过 getObject() 获取,就从三级缓存 singletonFactory.getObject() 中获取。一旦从三级缓存中获取到了,将 singletonFactories 中移除掉缓存,并将创建出的 bean 放入 earlySingletonObjects 中,其实也就是从三级缓存移动到了二级缓存。 可以通过 XmlBeanFactory.setAllowCircularReferences(false) 来禁用循环依赖,这样就Spring不会尝试解决这一问题,直接抛出异常
.
从工厂bean的实例中获取对象,这个方法是各种getbean的最后一步处理,之前保存的bean对象有可能是工厂类的实例,这里判断如果是工厂类的实例则通过工厂类的getObject()得到真实的bean,
(1)getObjectForBeanInstance判断合法,缓存,核心是调getObjectFromFactoryBean, (2)getObjectFromFactoryBean判断单例和非单例,核心调doGetObjectFromFactoryBean (3)doGetObjectFromFactoryBean里判断权限,核心调FactoryBean 的 getObject().
1、类型验证转换,设置 class 属性或者根据 className 来解析 class ;
2、对 MethodOverride 属性进行验证及标记; 3、aop入口,应用初始化前的处理器,解析指定 bean 是否存在应用初始化前的aop短路操作 resolveBeforeInstantiation;如果前处理已经得到了bean就调用后处理器,跳过doCreateBean 4、创建 bean。(doCreateBean) .1 、如果是单例模式,首先从缓存中尝试 remove 得到 BeanWrapper;
2、如果缓存中没有,则根据 BeanDefinition 转换为 BeanWrapper; 3、通过前两步,我们得到 BeanWrapper 后,进行 MergedBeanDefinitionPostProcessors 的应用。主要是 bean 合并后的处理,@AutoWire 就是基于这个方法实现诸如类型的预解析; 4、处理 bean 的依赖; 5、对bean进行填充,将各个属性值注入 bean; 6、循环依赖检查,检测已经加载的 bean 是否已经出现了依赖循环,并判断是否要抛出异常; 7、注册 DisposableBean。如果XML配置了 destory-method,这里需要注册以便于销毁 bean 的时候调用; 8、完成创建并返回。 9、原型模式创建bean 10、其他自定义情况(request、session、global session) 预先实现自定义的Scope保持在this.scopes缓存, 把本对象的getbean相关方法封装定义成一个ObjectFactory<?> 根据名称从.scopes缓存找到对应的Scope,调用Scope.get(beanName,ObjectFactory<?>)得到bean参考文章
Spring源码——bean的加载转载地址:http://ithwi.baihongyu.com/