Spring容器初始化、bean解析、getbean流程

Context介绍:

Context类图如下:
这里写图片描述

主要类功能

  • ApplicationContext:Context的核心接口,主要功能都是继承其他接口而来,ListableBeanFactory(获取和访问bean功能),MessageSource(解析消息,支持国际化),ApplicationEventPublisher(发布event到注册的lisnter),ResourcePatternResolver(load文件资源),…完了在补充
  • ConfigurableApplicationContext:继承 Lifecycle, Closeable有生命周期功能,添加Id,Environment,BeanFactoryPostProcessor,ApplicationListener的set或get方法,还有重要的refresh(把持久层的数据load到内存中,并clear掉所有的之前创建的bean,包括singletons)方法
  • AbstractApplicationContext:继承DefaultResourceLoader,具有load资源功能(包涵classloader和持久层资源),在这个类内主要作用:refresh的模板方法和ApplicationEvent发布功能
  • AbstractRefreshableApplicationContext:对父类refresh里面部分方法,二级方法的实现
  • AbstractRefreshableConfigApplicationContext对Context继承BeanNameAware, InitializingBean,使其有bean的特性,增加setConfigLocations方法
  • AbstractXmlApplicationContext:增加生成XmlBeanDefinitionReader并用reader load到持久化的bean的配置文件功能
  • ClassPathXmlApplicationContext:构造方法传入持久化配置文件路径

BeanFactory介绍:

BeanFactory接口类图如下:
这里写图片描述

主要类功能

  • BeanFactory:持有一些bean definitions,依赖bean definitions,根据name、type获取scope为Prototype,Singleton的bean
  • ListableBeanFactory:扩展BeanFactory接口,根据type,name返回bean集合,不需要每次一个一个获取
  • HierarchicalBeanFactory:用warp的方式实现了Bean工厂的分层,setParentBeanFactory方法在ConfigurableBeanFactory接口钟
  • ConfigurableBeanFactory:实现BeanClassLoader,SpEL表达式解释器,属性转化器,Scope,权限控制的setget方法;bean的依赖,是否创建销毁等方法
  • AutowireCapableBeanFactory:提供外部生成的bean注入根据name,class注入到容器中
  • ConfigurableListableBeanFactory:实现上面所有接口,有所有功能,对一下beandefinition 进行分析和修改
  • ConfigurableListableBeanFactory:实现上面所有接口,有所有功能,对一下beandefinition进行分析和修改
  • SingletonBeanRegistry:singletonBean接口,主要方法registerSingleton、getSingleton和一些其他辅助方法
  • AliasRegistry:Alias的注册删除等方法
  • SimpleAliasRegistry:用一个ConcurrentHashMap实现的AliasRegistry
  • DefaultSingletonBeanRegistry:实现singletonBean的注册,继承SimpleAliasRegistry,所以有别名功能
  • FactoryBeanRegistrySupport:扩展DefaultSingletonBeanRegistry功能,具体作用后面分析
  • AbstractBeanFactory 实现singleton和普通bean的get方法
  • AbstractAutowireCapableBeanFactory bean的创建, 属性, 绑定和初始化.处理运行时bean引用, 解析管理的集合, 调用初始化方法。
  • BeanDefinitionRegistry:bd注册功能
  • DefaultListableBeanFactory:实现了所有接口的功能,可以作为一个标准的beanfactory,也可以自定义BeanFactory的父类

Resource介绍:

Resource接口类图如下:
这里写图片描述

BeanDefinitionReader介绍:

BeanDefinitionReader接口类图如下:
这里写图片描述

BeanDefinition介绍:

BeanDefinition接口类图如下:
这里写图片描述

ResourceLoader介绍:

ResourceLoader接口类图如下:
这里写图片描述

解析BeanDefinition流程:

ApplicationContext做为容器中心(内部wrap一个beanfactory),
1. 把持久化文件转化resource
2. 读入以流的形势读到内存,BeanDefinitionReader以流形式解析resource成BeanDefinition
3. BeanDefinitionHolder对BeanDefinition进行wrap,注册到context wrap的beanfactory中

Bean解析流程:

下面开始从代码流程上分析Bean的解析过程:

使用代码如下:

        String file = "bean.xml";
        ClassPathXmlApplicationContext context1 = new ClassPathXmlApplicationContext(file);
        ModelA modelA = (ModelA) context1.getBean("modelA");
        System.out.println(modelA);

ClassPathXmlApplicationContext


    public ClassPathXmlApplicationContext(String configLocation) throws BeansException {
        this(new String[] {configLocation}, true, null);
    }
    public ClassPathXmlApplicationContext(String[] configLocations, boolean refresh, ApplicationContext parent)
            throws BeansException {

        super(parent);

        setConfigLocations(configLocations);
        if (refresh) {
            refresh();
        }
    }

两个主要方法:setConfigLocations,refresh,先跟setConfigLocations,功能主要两个:1.把占位符替换为真正的值 2.把值path设置到context中
AbstractRefreshableConfigApplicationContext

        public void setConfigLocations(String... locations) {
        if (locations != null) {
            Assert.noNullElements(locations, "Config locations must not be null");
            this.configLocations = new String[locations.length];
            for (int i = 0; i < locations.length; i++) {
                //把占位符号用环境变量或System.getProperties().get("key")替换
                this.configLocations[i] = resolvePath(locations[i]).trim();
            }
        }
        else {
            this.configLocations = null;
        }
    }
    protected String resolvePath(String path) {
       //getEnvironment(),可以返回一个StandardEnvironment,继续跟到AbstractPropertyResolver类
        return getEnvironment().resolveRequiredPlaceholders(path);//
    }

AbstractPropertyResolver

    public String resolveRequiredPlaceholders(String text) throws IllegalArgumentException {
        if (this.strictHelper == null) {
            this.strictHelper = createPlaceholderHelper(false);
        }
        return doResolvePlaceholders(text, this.strictHelper);
    }

    private String doResolvePlaceholders(String text, PropertyPlaceholderHelper helper) {
        //最终处理在PropertyPlaceholderHelper
        return helper.replacePlaceholders(text, new PropertyPlaceholderHelper.PlaceholderResolver() {
            @Override
            public String resolvePlaceholder(String placeholderName) {
                return getPropertyAsRawString(placeholderName);
            }
        });
    }
public String replacePlaceholders(String value, PlaceholderResolver placeholderResolver) {
        Assert.notNull(value, "'value' must not be null");
        return parseStringValue(value, placeholderResolver, new HashSet<String>());
    }
    //核心方法
    //strVal = "${key:bean$}.xml" 带默认值
    //strVal = "${key${keyiner}}.xml" 带嵌套子占位符
    protected String parseStringValue(
            String strVal, PlaceholderResolver placeholderResolver, Set<String> visitedPlaceholders) {

        StringBuilder result = new StringBuilder(strVal);
        //this.placeholderPrefix='${',这个值可以修改
        int startIndex = strVal.indexOf(this.placeholderPrefix);
        while (startIndex != -1) {
            //找到对应${的}
            //找的逻辑很简单,用index变量,从前往后找,匹配到前缀index++,匹配到后缀且index>0,index--,否则命中,如果什么都匹配继续找
            int endIndex = findPlaceholderEndIndex(result, startIndex);
            if (endIndex != -1) {
                String placeholder = result.substring(startIndex + this.placeholderPrefix.length(), endIndex);
                String originalPlaceholder = placeholder;
                if (!visitedPlaceholders.add(originalPlaceholder)) {
                    throw new IllegalArgumentException(
                            "Circular placeholder reference '" + originalPlaceholder + "' in property definitions");
                }
                //这个递归的作用先替换子占位符,及先找出嵌套子占位符的${keyiner},用值替换
                // Recursive invocation, parsing placeholders contained in the placeholder key.
                //
                placeholder = parseStringValue(placeholder, placeholderResolver, visitedPlaceholders);
                // Now obtain the value for the fully resolved key...
                //到StandardEnvironment注册的Propertie和evn找替换占位符的value
                String propVal = placeholderResolver.resolvePlaceholder(placeholder);
                //没有找到,获取默认值,"${key:bean$}.xml"中的bean
                if (propVal == null && this.valueSeparator != null) {
                    int separatorIndex = placeholder.indexOf(this.valueSeparator);
                    if (separatorIndex != -1) {
                        String actualPlaceholder = placeholder.substring(0, separatorIndex);
                        String defaultValue = placeholder.substring(separatorIndex + this.valueSeparator.length());
                        propVal = placeholderResolver.resolvePlaceholder(actualPlaceholder);
                        if (propVal == null) {
                            propVal = defaultValue;
                        }
                    }
                }
                if (propVal != null) {
                    // Recursive invocation, parsing placeholders contained in the
                    // previously resolved placeholder value.
                    //和上面递归类似,这个是evn或prop中有占位符
                    propVal = parseStringValue(propVal, placeholderResolver, visitedPlaceholders);
                    result.replace(startIndex, endIndex + this.placeholderSuffix.length(), propVal);
                    if (logger.isTraceEnabled()) {
                        logger.trace("Resolved placeholder '" + placeholder + "'");
                    }
                    startIndex = result.indexOf(this.placeholderPrefix, startIndex + propVal.length());
                }
                else if (this.ignoreUnresolvablePlaceholders) {
                    // Proceed with unprocessed value.
                    startIndex = result.indexOf(this.placeholderPrefix, endIndex + this.placeholderSuffix.length());
                }
                else {
                    throw new IllegalArgumentException("Could not resolve placeholder '" +
                            placeholder + "'" + " in string value \"" + strVal + "\"");
                }
                visitedPlaceholders.remove(originalPlaceholder);
            }
            else {
                startIndex = -1;
            }
        }

        return result.toString();
    }

下面跟refresh方法,refresh主要模版在父类AbstractApplicationContext中,

AbstractApplicationContext.refresh

    @Override
    public void refresh() throws BeansException, IllegalStateException {
        //枷锁,refresh逻辑同时只有一个线程,close方法也用的这个锁,保证只能同时执行一个方法
        synchronized (this.startupShutdownMonitor) {
            // Prepare this context for refreshing.
            //设置启动时间、一些标志位、初始化一些全局变量等
            prepareRefresh();

            // Tell the subclass to refresh the internal bean factory.
            //真正BeanFactory创建方法,上面主要分析这个方法
            ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

            // Prepare the bean factory for use in this context.
            //对beanfactory
            prepareBeanFactory(beanFactory);

            try {
                // Allows post-processing of the bean factory in context subclasses.
                //子类prepare,如果子类类似webcontext,evnbean,特殊bean,在这里实现。它的作用同前一个方法
                postProcessBeanFactory(beanFactory);

                // Invoke factory processors registered as beans in the context.
                //BeanFactoryPostProcessor的实现方法被调用
                invokeBeanFactoryPostProcessors(beanFactory);

                // Register bean processors that intercept bean creation.
                //把BeanPostProcessor注册到beanFactory的一个list中
                registerBeanPostProcessors(beanFactory);

                // Initialize message source for this context.
                //国际化相关,
                initMessageSource();

                // Initialize event multicaster for this context.
                //context是实现了ApplicationEventPublisher,
                //如果没有配置applicationEventMulticaster,则注册单例new SimpleApplicationEventMulticaster();
                initApplicationEventMulticaster();

                // Initialize other special beans in specific context subclasses.
                //默认空实现,为子类在实例singletonsBean之前,可以实例先特殊bean
                onRefresh();

                // Check for listener beans and register them.
                //把listener注册到到applicationEventMulticaster中
                registerListeners();

                // Instantiate all remaining (non-lazy-init) singletons.
                //初始化所有非懒加载的单例bean
                //重要方法,跟进分析
                finishBeanFactoryInitialization(beanFactory);

                // Last step: publish corresponding event.
                //发个context event,get生命周期的相关bean,注册一些全局变量
                finishRefresh();
            }

            catch (BeansException ex) {
                if (logger.isWarnEnabled()) {
                    logger.warn("Exception encountered during context initialization - " +
                            "cancelling refresh attempt: " + ex);
                }

                // Destroy already created singletons to avoid dangling resources.
                //如果挂了,清除单例bean,避免浪费资源
                destroyBeans();

                // Reset 'active' flag.
                //重置标志位
                cancelRefresh(ex);

                // Propagate exception to caller.
                throw ex;
            }

            finally {
                // Reset common introspection caches in Spring's core, since we
                // might not ever need metadata for singleton beans anymore...
                resetCommonCaches();
            }
        }
    }

先看下prepareRefresh方法
AbstractApplicationContext

protected void prepareRefresh() {
        //纪录启动时间,设置标志位
        this.startupDate = System.currentTimeMillis();
        this.closed.set(false);
        this.active.set(true);

        if (logger.isInfoEnabled()) {
            logger.info("Refreshing " + this);
        }

        // Initialize any placeholder property sources in the context environment

        //env等初始化一些全局的property
        initPropertySources();

        // Validate that all properties marked as required are resolvable
        // see ConfigurablePropertyResolver#setRequiredProperties
        //validate必要prop全部有,如果没有throws异常
        getEnvironment().validateRequiredProperties();

        // Allow for the collection of early ApplicationEvents,
        // to be published once the multicaster is available...
        this.earlyApplicationEvents = new LinkedHashSet<ApplicationEvent>();
    }

obtainFreshBeanFactory这个时重点方法,配置文件的加载、解析、注册
AbstractApplicationContext

    protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
        //主要的初始化功能在这个方法
        refreshBeanFactory();
        ConfigurableListableBeanFactory beanFactory = getBeanFactory();
        if (logger.isDebugEnabled()) {
            logger.debug("Bean factory for " + getDisplayName() + ": " + beanFactory);
        }
        return beanFactory;
    }

AbstractRefreshableApplicationContext

    @Override
    protected final void refreshBeanFactory() throws BeansException {
        //如果之前存在BeanFactory
        if (hasBeanFactory()) {
            //destory此BeanFactory注册的单例bean
            destroyBeans();
            //置为当前wrap引用指向null
            closeBeanFactory();
        }
        try {
            //new BeanFactory
            DefaultListableBeanFactory beanFactory = createBeanFactory();
            //把beanFactory和当前Context用id关联
            beanFactory.setSerializationId(getId());
            //设置把Contxt的一些标志设置给BeanFactory,这里主要有两个
            //allowBeanDefinitionOverriding(bean同名 覆盖or exception),allowCircularReferences(bean可以循环引用)
            customizeBeanFactory(beanFactory);
            //主要方法,继续跟
            loadBeanDefinitions(beanFactory);
            synchronized (this.beanFactoryMonitor) {
                this.beanFactory = beanFactory;
            }
        }
        catch (IOException ex) {
            throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex);
        }
    }

真正创建的factory是DefaultListableBeanFactory
AbstractRefreshableApplicationContext

protected DefaultListableBeanFactory createBeanFactory() {
        return new DefaultListableBeanFactory(getInternalParentBeanFactory());
    }

loadBeanDefinitions实现在子类中,因为不同的配置文件需要是不同的resource,也需要不同的reader
AbstractXmlApplicationContext.loadBeanDefinitions

@Override
    protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws BeansException, IOException {
        // Create a new XmlBeanDefinitionReader for the given BeanFactory.
        XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);

        // Configure the bean definition reader with this context's
        // resource loading environment.
        //把context的env设置Reader中
        beanDefinitionReader.setEnvironment(this.getEnvironment());
        //把context的ResouceLoader设置Reader中,Context继承DefaultResourceLoader
        beanDefinitionReader.setResourceLoader(this);
        //xml中spring相关的dtd和schema的entiryResolver
        beanDefinitionReader.setEntityResolver(new ResourceEntityResolver(this));

        // Allow a subclass to provide custom initialization of the reader,
        // then proceed with actually loading the bean definitions.
        //英文注释是用来子类自定义的
        initBeanDefinitionReader(beanDefinitionReader);
        //这个跟进
        loadBeanDefinitions(beanDefinitionReader);
    }

查看XmlBeanDefinitionReader父类AbstractBeanDefinitionReader中构造方法
AbstractBeanDefinitionReader.AbstractBeanDefinitionReader

protected AbstractBeanDefinitionReader(BeanDefinitionRegistry registry) {
        Assert.notNull(registry, "BeanDefinitionRegistry must not be null");
        //把DefaultListableBeanFactory实现了BeanDefinitionRegistry接
        this.registry = registry;

        // Determine ResourceLoader to use.
        //DefaultListableBeanFactory没有实现ResourceLoader,所以走else
        if (this.registry instanceof ResourceLoader) {
            this.resourceLoader = (ResourceLoader) this.registry;
        }
        else {
            this.resourceLoader = new PathMatchingResourcePatternResolver();
        }
        //DefaultListableBeanF
  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值