前情回顾前文「Spring 如何从 IoC 容器中获取对象?」从整体上分析了如何从 Spring IoC 容器获取一个 bean 对象。该逻辑由 AbstractBeanFactory#doGetBean 方法实现,主要流程如下:

目前成都创新互联公司已为千余家的企业提供了网站建设、域名、虚拟空间、绵阳服务器托管、企业网站设计、揭西网站维护等服务,公司将坚持客户导向、应用为本的策略,正道将秉承"和谐、参与、激情"的文化,与客户和合作伙伴齐心协力一起成长,共同发展。
本文进一步深入细节,主要分析如何创建 singleton(单例)类型的对象。
如何创建单例对象?
从流程图可以看出,当获取一个 bean 对象时,Spring 会首先尝试从缓存中获取单例对象。
值得注意是的:
既然能取,必然有地方把 bean 对象存入了缓存,那缓存中的数据是从哪里来的呢?
下面主要分析单例对象是如何创建、并放入缓存中的。
该逻辑在 AbstractBeanFactory#doGetBean 方法中,主要代码如下(保留了创建单例 bean 对象的代码,其他部分暂时忽略):
- public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport implements ConfigurableBeanFactory {
 - // ...
 - protected
 T doGetBean( - String name, @Nullable Class
 requiredType, @Nullable Object[] args, boolean typeCheckOnly) - throws BeansException {
 - String beanName = transformedBeanName(name);
 - Object bean;
 - // 从缓存中获取单例 bean 对象
 - Object sharedInstance = getSingleton(beanName);
 - // 缓存中不存在 bean 对象
 - else {
 - // ...
 - try {
 - // 获取 BeanDefinition
 - RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
 - // 获取依赖的 bean 对象
 - // 若创建一个 bean 对象时依赖其他对象,则先创建被依赖对象
 - // ...
 - // 创建 scope 为 singleton(单例)的对象
 - if (mbd.isSingleton()) {
 - sharedInstance = getSingleton(beanName, () -> {
 - try {
 - return createBean(beanName, mbd, args);
 - }
 - catch (BeansException ex) {
 - // ...
 - }
 - });
 - // 处理 FactoryBean 的场景
 - bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
 - }
 - // 创建 scope 为 prototype 的对象
 - else if (mbd.isPrototype()) {
 - // ...
 - }
 - // 创建其他类型对象
 - else {
 - // ...
 - }
 - }
 - catch (BeansException ex) {
 - // ...
 - }
 - }
 - // 类型检查
 - return (T) bean;
 - }
 - }
 
其实就是这个 DefaultSingletonBeanRegistry#getSingleton 方法,代码如下:
- public class DefaultSingletonBeanRegistry extends SimpleAliasRegistry implements SingletonBeanRegistry {
 - // 单例 bean 对象缓存(beanName, bean)
 - private final Map
 singletonObjects = new ConcurrentHashMap<>(256); - public Object getSingleton(String beanName, ObjectFactory> singletonFactory) {
 - Assert.notNull(beanName, "Bean name must not be null");
 - synchronized (this.singletonObjects) {
 - // 先从缓存中获取 bean 对象
 - Object singletonObject = this.singletonObjects.get(beanName);
 - // 缓存中不存在时再去创建
 - if (singletonObject == null) {
 - // ...
 - // 创建单例对象前
 - beforeSingletonCreation(beanName);
 - boolean newSingleton = false;
 - boolean recordSuppressedExceptions = (this.suppressedExceptions == null);
 - if (recordSuppressedExceptions) {
 - this.suppressedExceptions = new LinkedHashSet<>();
 - }
 - try {
 - // 创建单例对象
 - singletonObject = singletonFactory.getObject();
 - newSingleton = true;
 - }
 - // catch ...
 - finally {
 - if (recordSuppressedExceptions) {
 - this.suppressedExceptions = null;
 - }
 - // 创建单例对象后
 - afterSingletonCreation(beanName);
 - }
 - if (newSingleton) {
 - // 将对象添加到缓存
 - addSingleton(beanName, singletonObject);
 - }
 - }
 - // 缓存中有的话直接返回
 - return singletonObject;
 - }
 - }
 - }
 
getSingleton 方法会先从缓存 singletonObjects(其实就是一个 Map)中获取 bean 对象,如果缓存有就直接返回,否则再去创建。创建成功后,会把该对象存入缓存。
创建的逻辑在哪呢?
看代码是通过 ObjectFactory#getObject 方法来创建的,ObjectFactory 是一个函数式接口:
- @FunctionalInterface
 - public interface ObjectFactory
 { - T getObject() throws BeansException;
 - }
 
这个方法的实现是什么呢?退回上一层,即 getBean 方法,看这里:
- sharedInstance = getSingleton(beanName, () -> {
 - try {
 - // 创建 bean 对象
 - return createBean(beanName, mbd, args);
 - }
 - catch (BeansException ex) {
 - // ...
 - }
 - });
 
这里用到了 Lambda 表达式,将如下表达式作为参数:
- () -> {
 - try {
 - // 创建 bean 对象
 - return createBean(beanName, mbd, args);
 - }
 - catch (BeansException ex) {
 - // ...
 - }
 - }
 
创建 bean 对象的逻辑就在这个 createBean 方法中,它在 AbstractAutowireCapableBeanFactory 类中:
- public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFactory
 - implements AutowireCapableBeanFactory {
 - @Override
 - protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
 - throws BeanCreationException {
 - RootBeanDefinition mbdToUse = mbd;
 - Class> resolvedClass = resolveBeanClass(mbd, beanName);
 - if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) {
 - mbdToUse = new RootBeanDefinition(mbd);
 - mbdToUse.setBeanClass(resolvedClass);
 - }
 - // Prepare method overrides.
 - try {
 - mbdToUse.prepareMethodOverrides();
 - }
 - // catch ...
 - try {
 - // Give BeanPostProcessors a chance to return a proxy instead of the target bean instance.
 - // 这里可能返回代理对象
 - Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
 - if (bean != null) {
 - return bean;
 - }
 - }
 - // catch ...
 - try {
 - // 创建 bean 对象
 - Object beanInstance = doCreateBean(beanName, mbdToUse, args);
 - if (logger.isTraceEnabled()) {
 - logger.trace("Finished creating instance of bean '" + beanName + "'");
 - }
 - return beanInstance;
 - }
 - // catch ...
 - }
 - }
 
这里继续沿着主线逻辑走。
创建 bean 对象是在 doCreateBean 方法中实现的,如下:
- public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFactory
 - implements AutowireCapableBeanFactory {
 - protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
 - throws BeanCreationException {
 - // Instantiate the bean.
 - // 1. 实例化 bean
 - BeanWrapper instanceWrapper = null;
 - if (mbd.isSingleton()) {
 - instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
 - }
 - if (instanceWrapper == null) {
 - instanceWrapper = createBeanInstance(beanName, mbd, args);
 - }
 - Object bean = instanceWrapper.getWrappedInstance();
 - Class> beanType = instanceWrapper.getWrappedClass();
 - if (beanType != NullBean.class) {
 - mbd.resolvedTargetType = beanType;
 - }
 - // Allow post-processors to modify the merged bean definition.
 - synchronized (mbd.postProcessingLock) {
 - if (!mbd.postProcessed) {
 - try {
 - applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
 - }
 - // catch ...
 - mbd.postProcessed = true;
 - }
 - }
 - boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
 - isSingletonCurrentlyInCreation(beanName));
 - if (earlySingletonExposure) {
 - addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
 - }
 - // Initialize the bean instance.
 - Object exposedObject = bean;
 - try {
 - // 2. 填充属性
 - populateBean(beanName, mbd, instanceWrapper);
 - // 3. 初始化
 - exposedObject = initializeBean(beanName, exposedObject, mbd);
 - }
 - // catch ...
 - if (earlySingletonExposure) {
 - Object earlySingletonReference = getSingleton(beanName, false);
 - if (earlySingletonReference != null) {
 - if (exposedObject == bean) {
 - exposedObject = earlySingletonReference;
 - }
 - else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) {
 - String[] dependentBeans = getDependentBeans(beanName);
 - Set
 actualDependentBeans = new LinkedHashSet<>(dependentBeans.length); - for (String dependentBean : dependentBeans) {
 - if (!removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) {
 - actualDependentBeans.add(dependentBean);
 - }
 - }
 - // ...
 - }
 - }
 - }
 - // Register bean as disposable.
 - try {
 - registerDisposableBeanIfNecessary(beanName, bean, mbd);
 - }
 - // catch ...
 - return exposedObject;
 - }
 - }
 
这个方法看起来有点长,但最主要的事情只有三件:
这几个方法内部其实都有一大堆堆堆堆堆……的代码,再对照一下前面给出的整体流程图 :
就是这样。
本文在前文整体分析的基础上又进一步细化,先到这里吧,后面再继续分析~
小结
如何从 Spring IoC 容器中获取 bean 对象?前文对此进行了整体流程的分析。
本文在前文的基础上又进一步细化,主要从整体上探讨了 Spring 如何创建单例的 bean 对象,整体上分为三个步骤:
至于这三个步骤具体又做了什么,且听下回分解。
                网站名称:详解Spring如何创建Bean对象?
                
                链接URL:http://www.csdahua.cn/qtweb/news8/106558.html
            
网站建设、网络推广公司-快上网,是专注品牌与效果的网站制作,网络营销seo公司;服务项目有等
声明:本网站发布的内容(图片、视频和文字)以用户投稿、用户转载内容为主,如果涉及侵权请尽快告知,我们将会在第一时间删除。文章观点不代表本网站立场,如需处理请联系客服。电话:028-86922220;邮箱:631063699@qq.com。内容未经允许不得转载,或转载时需注明来源: 快上网