prepareBeanFactory方法源码跟踪

看这篇文章之前可以先了解之前的跟踪流程,https://www.jianshu.com/p/4934233f0ead

代码过宽,可以shift + 鼠标滚轮 左右滑动查看

AbstractApplicationContext类refresh()方法中的第三个调用方法prepareBeanFactory()的跟踪。

@Override
public void refresh() throws BeansException, IllegalStateException {
    synchronized (this.startupShutdownMonitor) {
        ...
        // Prepare the bean factory for use in this context.
        // 准备在上下文中bean factory的使用
        prepareBeanFactory(beanFactory);
        ···
 }

断点进入跟踪。

此方法的实现在AbstractApplicationContext类中。

prepareBeanFactory(零)

/**
* Configure the factory's standard context characteristics,
* such as the context's ClassLoader and post-processors.
*
* 配置工厂的标准上下文特征,比如上下文的ClassLoader和post-processors
*/
protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) {
    
    // Tell the internal bean factory to use the context's class loader etc.
    //告知内部的bean工厂,使用上下文的类加载器
    beanFactory.setBeanClassLoader(getClassLoader());
    
    //设置bean表达式解析器,
    //StandardBeanExpressionResolver内部expressionParser属性默认SpelExpressionParser类型
    //spel = spring el表达式
    beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader()));
    
    //将ResourceEditorRegistrar实例添加到工厂的propertyEditorRegistrars属性中,
    //propertyEditorRegistrars是一个LinkedHashSet,里面的元素将会应用到工厂bean中
    //ResourceEditorRegistrar持有上下文和environment的引用
    beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment()));

    // Configure the bean factory with context callbacks.
    // 使用上下文回调配置bean 工厂
    //在工厂的beanPostProcessor属性中添加处理器,beanPostProcessor是一个ArrayList
    beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));
    
    //在工厂的ignoredDependencyInterfaces属性中添加Aware系列接口,
    //ignoredDependencyInterfaces是一个HashSet
    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接口并没有按照resolvable类型进行注册
    // MessageSource被注册成一个Bean(并被自动注入)
    
    //BeanFactory.class为key,beanFactory为value放入到了beanFactory的resolvableDependencies属性中
    //resolvableDependencies是一个ConcurrentHashMap,映射依赖类型和对应的被注入的value
    //这样的话BeanFactory/ApplicationContext虽然没有以bean的方式被定义在工厂中,
    //但是也能够支持自动注入,因为他处于resolvableDependencies属性中
    beanFactory.registerResolvableDependency(BeanFactory.class, beanFactory);
    
    //再将上下文的一些接口与上下文本身做映射,一一放入到resolvableDependencies中
    beanFactory.registerResolvableDependency(ResourceLoader.class, this);
    beanFactory.registerResolvableDependency(ApplicationEventPublisher.class, this);
    beanFactory.registerResolvableDependency(ApplicationContext.class, this);

    // Detect a LoadTimeWeaver and prepare for weaving, if found.
    // 检测LoadTimeWeaver,如果有就准备织入
    //1.跟踪进入,浅看下containsBean方法
    if (beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
        
        //如果有LoadTimeWeaver,加入bean后处理器
        beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
        
        // Set a temporary ClassLoader for type matching.
        // 为匹配类型设置一个临时的ClassLoader
        beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
    }

    // Register default environment beans.
    // 注册默认的environment beans
    
    // 判断目前这个bean工厂中是否包含指定name的bean,忽略父工厂
    if (!beanFactory.containsLocalBean(ENVIRONMENT_BEAN_NAME)) {
        
        //虽然XmlWebApplicationContext中持有默认实现的StandardServletEnvironment
        //但是没有注册到beanFactory中,通过getEnvironment方法拿到持有的引用
        //2.注册environment单例
        beanFactory.registerSingleton(ENVIRONMENT_BEAN_NAME, getEnvironment());
    }
    if (!beanFactory.containsLocalBean(SYSTEM_PROPERTIES_BEAN_NAME)) {
        
        //注册systemProperties单例
        beanFactory.registerSingleton(SYSTEM_PROPERTIES_BEAN_NAME, getEnvironment().getSystemProperties());
    }
    if (!beanFactory.containsLocalBean(SYSTEM_ENVIRONMENT_BEAN_NAME)) {
        
        //注册systemEnvironment单例
        beanFactory.registerSingleton(SYSTEM_ENVIRONMENT_BEAN_NAME, getEnvironment().getSystemEnvironment());
    }
}

1.containsBean

跟踪标记为1的方法

此方法的实现在AbstractBeanFactory类中

//1.跟踪看下containsBean方法
beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)

    
/**
* Does this bean factory contain a bean definition or externally registered singleton
* instance with the given name?
* <p>If the given name is an alias, it will be translated back to the corresponding
* canonical bean name.
* <p>If this factory is hierarchical, will ask any parent factory if the bean cannot
* be found in this factory instance.
* <p>If a bean definition or singleton instance matching the given name is found,
* this method will return {@code true} whether the named bean definition is concrete
* or abstract, lazy or eager, in scope or not. Therefore, note that a {@code true}
* return value from this method does not necessarily indicate that {@link #getBean}
* will be able to obtain an instance for the same name.
*
* bean工厂是否包含一个给定name的bean definition,或者外部被注册的单例bean?
* 如果name是一个别名,会被转换成对应的beanName
* 如果工厂是有层级的,那么当工厂实例中找不到这个bean时,就会去父工厂中查找
* 如果找到匹配name的bean definition或者单例,那么这个方法会返回true
* 不管这个bean definition是具体的还是抽象的,提前加载还是懒加载,是否在范围中。
* 因此,注意从这个方法中返回的true值并不代表从getBean方法中能够获取一个同名称的实例
*/
@Override
public boolean containsBean(String name) {
    
    //1.1对name进行必要的转换
    String beanName = transformedBeanName(name);
    
    //singletonObjects或者beanDefinitionMap中已注册beanName则进入条件
    //说明该beanName有对应的bean definition,或者单例bean
    if (containsSingleton(beanName) || containsBeanDefinition(beanName)) {
        
        //name开头不为&返回true,如果带了&但是是FactoryBean也返回true
        //要注意下FactoryBean和BeanFactory的区别,可以看下文参考链接
        return (!BeanFactoryUtils.isFactoryDereference(name) || isFactoryBean(name));
    }
    
    // Not found -> check parent.
    // 如果没有找到对应beanName的bean或者bean definition,那么从父工厂查找
    BeanFactory parentBeanFactory = getParentBeanFactory();
    
    return (parentBeanFactory != null && parentBeanFactory.containsBean(originalBeanName(name)));
}

1.1 transformedBeanName

跟踪标记为1.1的方法

此方法的实现在AbstractBeanFactory类中

//1.1对name进行必要的转换
String beanName = transformedBeanName(name);

/**
* Return the bean name, stripping out the factory dereference prefix if necessary,
* and resolving aliases to canonical names.
*
* 返回bean name,剥离factory dereference 前缀,并将别名解析为bean name
*/
protected String transformedBeanName(String name) {
    
    //总的来说,如果name代表factory,那么name前就带有&前缀,去掉此前缀
    //如果这个name是beanName,则直接返回,如果name是alias,在aliasMap中查找对应的beanName,再返回
    return canonicalName(BeanFactoryUtils.transformedBeanName(name));
}

//先看下transformedBeanName方法的实现
//进入BeanFactoryUtils类中
/**
* Return the actual bean name, stripping out the factory dereference
* prefix (if any, also stripping repeated factory prefixes if found).
*
* 返回真实的beanName,剥离工厂前缀(如果有的话,也剥离重复的工厂前缀)
*/
public static String transformedBeanName(String name) {
    Assert.notNull(name, "'name' must not be null");
    String beanName = name;
    //FACTORY_BEAN_PREFIX常量为:&
    while (beanName.startsWith(BeanFactory.FACTORY_BEAN_PREFIX)) {
        beanName = beanName.substring(BeanFactory.FACTORY_BEAN_PREFIX.length());
    }
    return beanName;
}


//再进入canonicalName方法查看
//此方法在SimpleAliasRegistry中实现,被默认bean工厂间接继承
/**
* Determine the raw name, resolving aliases to canonical names.
*
* 确定原生的name,将别名解析为BeanName
*/
public String canonicalName(String name) {
    String canonicalName = name;
    
    // Handle aliasing...
    // 处理别名
    String resolvedName;
    do {
        
        //拿到canonicalName对应的实际名称
        resolvedName = this.aliasMap.get(canonicalName);
        if (resolvedName != null) {
            canonicalName = resolvedName;
        }
    }
    
    //只有当canonicalName在aliasMap中对应的value为null时,才跳出循环
    //这时候说明canonicalName已经不作为其他任何BeanName的别名,排除了间接引用
    //canonicalName就为真正的beanName
    while (resolvedName != null);
    return canonicalName;
}

2.registerSingleton

跟踪标记为2的方法

此方法的实现在DefaultListableBeanFactory类中

//2.注册environment单例
beanFactory.registerSingleton(ENVIRONMENT_BEAN_NAME, getEnvironment());


@Override
public void registerSingleton(String beanName, Object singletonObject) throws IllegalStateException {
    
    //2.1调用父类方法,注册单例
    super.registerSingleton(beanName, singletonObject);

    //AbstractBeanFactory类中有个集合属性alreadyCreated
    //里面保存在至少被创建过一次的beanName
    //如果这个集合中存在beanName,那么说明已经进入了bean创建阶段
    if (hasBeanCreationStarted()) {
        
        // Cannot modify startup-time collection elements anymore (for stable iteration)
        // 无法再修改启动时集合元素(为了稳定迭代)
        synchronized (this.beanDefinitionMap) {
            
            //beanName不在beanDefinitionMap中,说明是手动注册
            if (!this.beanDefinitionMap.containsKey(beanName)) {
                Set<String> updatedSingletons = new LinkedHashSet<String>(this.manualSingletonNames.size() + 1);
                updatedSingletons.addAll(this.manualSingletonNames);
                updatedSingletons.add(beanName);
                this.manualSingletonNames = updatedSingletons;
            }
        }
    }
    else {
        
        // Still in startup registration phase
        // 仍然处于启动注册阶段
        if (!this.beanDefinitionMap.containsKey(beanName)) {
            
            //属于手动注册情况
            //environment属于手动注册单例
            this.manualSingletonNames.add(beanName);
        }
    }
    
    //进入这个方法查看
    clearByTypeCache();
}


/**
* Remove any assumptions about by-type mappings.
*
* 删除按照类型映射有关的任何假设
*/
private void clearByTypeCache() {
    
    //allBeanNamesByType是单例和非单例beanName的映射,key是依赖类型
    this.allBeanNamesByType.clear();
    
    //仅单例beanName的映射,key是依赖类型
    this.singletonBeanNamesByType.clear();
}

2.1 registerSingleton

跟踪标记为2.1的方法

此方法的实现在DefaultSingletonBeanRegistry类中

//2.1调用父类方法,注册单例
super.registerSingleton(beanName, singletonObject);


/**
* Register the given existing object as singleton in the bean registry,
* under the given bean name.
* <p>The given instance is supposed to be fully initialized; the registry
* will not perform any initialization callbacks (in particular, it won't
* call InitializingBean's {@code afterPropertiesSet} method).
* The given instance will not receive any destruction callbacks
* (like DisposableBean's {@code destroy} method) either.
* <p>When running within a full BeanFactory: <b>Register a bean definition
* instead of an existing instance if your bean is supposed to receive
* initialization and/or destruction callbacks.</b>
* <p>Typically invoked during registry configuration, but can also be used
* for runtime registration of singletons. As a consequence, a registry
* implementation should synchronize singleton access; it will have to do
* this anyway if it supports a BeanFactory's lazy initialization of singletons.
* 
* 在给定的bean name下,将存在的对象作为单例注册在工厂中
* 给定的实例应该是完全初始化;工厂不执行任何初始化回调(特别是,他不会调用InitializingBean的
* afterPropertiesSet方法)
* 给定的实例也不接收任何销毁回调(像DisposableBean的destroy方法)
* 当在完整的BeanFactory运行时:
* 如果你的bean需要接收初始化或者销毁的回调,注册一个bean definition替代一个存在的实例
* 通常此方法在工厂配置时被调用,也能在运行时单例注册时被调用。
* 作为结果,工厂的实现应该同步单例的访问;如果支持BeanFactory的单例的延迟初始化就不得不这样做
*/
@Override
public void registerSingleton(String beanName, Object singletonObject) throws IllegalStateException {
    Assert.notNull(beanName, "'beanName' must not be null");
    synchronized (this.singletonObjects) {
        Object oldObject = this.singletonObjects.get(beanName);
        
        //不能注册两次
        if (oldObject != null) {
            throw new IllegalStateException("Could not register object [" + singletonObject +
                                            "] under bean name '" + beanName + "': there is already object [" + oldObject + "] bound");
        }
        
        //进入这个方法
        addSingleton(beanName, singletonObject);
    }
}

/**
* Add the given singleton object to the singleton cache of this factory.
* <p>To be called for eager registration of singletons.
*
* 添加给定单例对象到工厂的单例缓存中
* 用来被提早注册的单例调用
*/
protected void addSingleton(String beanName, Object singletonObject) {
    synchronized (this.singletonObjects) {
        
        //singletonObjects是一个ConcurrentHashMap
        //用来缓存单例对象
        this.singletonObjects.put(beanName, (singletonObject != null ? singletonObject : NULL_OBJECT));
        
        //singletonFactories是一个HashMap
        //里面缓存着单例工厂
        this.singletonFactories.remove(beanName);
        
        //早期单例对象
        //earlySingletonObjects是一个HashMap
        this.earlySingletonObjects.remove(beanName);
        
        //registeredSingletons是一个LinkedHashSet
        //被注册单例的集合,以注册的顺序包含着bean name
        this.registeredSingletons.add(beanName);
    }
}

这样,整个prepareBeanFactory方法也就跟踪完毕了。

接下来跟踪postProcessBeanFactory方法:
https://www.jianshu.com/p/c05aea93b939

参考

BeanFactory和FactoryBean的区别:https://www.cnblogs.com/aspirant/p/9082858.html

总结

  • 为工厂设置类的加载器、表达式解析器、属性编辑器注册器等
  • 为工厂添加后处理器、要忽略的依赖接口
  • 在工厂中注册可解析的依赖
  • 在工厂中提前注册一些单例Bean
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,684评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,143评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,214评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,788评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,796评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,665评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,027评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,679评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 41,346评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,664评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,766评论 1 331
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,412评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,015评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,974评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,203评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,073评论 2 350
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,501评论 2 343

推荐阅读更多精彩内容