zoukankan      html  css  js  c++  java
  • 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
  • 相关阅读:
    选择学习Web前端开发的理由
    在Nginx下部署SSL证书并重定向至HTTPS
    使用pm2快速将项目部署到远程服务器
    DNS域名解析过程
    HTML5新特性总结
    基于 HTML5 Canvas 的智能安防 SCADA 巡逻模块
    react中使用css的7种方式
    原生JS实现滑动轮播图
    H5与企业微信jssdk集成
    img图片不存在显示默认图
  • 原文地址:https://www.cnblogs.com/feng-jq/p/10282256.html
Copyright © 2011-2022 走看看