专注于 JetBrains IDEA 全家桶,永久激活,教程
持续更新 PyCharm,IDEA,WebStorm,PhpStorm,DataGrip,RubyMine,CLion,AppCode 永久激活教程

Spring

##1. ClassPathXmlApplicationContext

public ClassPathXmlApplicationContext(String[] configLocations, boolean refresh, ApplicationContext parent) {
    //null
    super(parent);
    setConfigLocations(configLocations);
    //默认true
    if (refresh) {
        refresh();
    }

###1.1 super()一路向上调用,直到AbstractApplicationContext

public AbstractApplicationContext(ApplicationContext parent) {
        this();
        this.setParent(parent);
    }

public AbstractApplicationContext() {
        this.logger = LogFactory.getLog(this.getClass());
        this.id = ObjectUtils.identityToString(this);
        this.displayName = ObjectUtils.identityToString(this);
        this.beanFactoryPostProcessors = new ArrayList();
        this.active = new AtomicBoolean();
        this.closed = new AtomicBoolean();
        this.startupShutdownMonitor = new Object();
        this.applicationListeners = new LinkedHashSet();
        this.resourcePatternResolver = this.getResourcePatternResolver();
    }

protected ResourcePatternResolver getResourcePatternResolver() {
        //路径解析
        return new PathMatchingResourcePatternResolver(this);
    }

public PathMatchingResourcePatternResolver(ResourceLoader resourceLoader) {
        Assert.notNull(resourceLoader, "ResourceLoader must not be null");
        this.resourceLoader = resourceLoader;
    }

PathMatchingResourcePatternResolver支持Ant风格的路径解析。 ###1.2 设置配置文件路径:ClassPathXmlApplicationContext.setConfigLocations(configLocations) AbstractRefreshableConfigApplicationContext.setConfigLocations

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) {
                //将占位符(placeholder)解析成实际的地址
                this.configLocations[i] = this.resolvePath(locations[i]).trim();
            }
        } else {
            this.configLocations = null;
        }
    }

AbstractRefreshableConfigApplicationContext.resolvePath()

protected String resolvePath(String path) {
        return this.getEnvironment().resolveRequiredPlaceholders(path);
    }

####1.2.1 Environment接口 上一步resolvePath(String path)中用到了getEnvironment().resolveRequiredPlaceholders(path),Environment接口主要包含了针对Property的一些操作:

  • 首先getEnvironment()获取Environment:如果Environment为null则new一个StandardEnvironment出来: AbstractApplicationContext.createEnvironment()
protected ConfigurableEnvironment createEnvironment() {
        return new StandardEnvironment();
    }

而StandardEnvironment继承于AbstractEnvironment,AbstractEnvironment中包含MutablePropertySources属性:

public abstract class AbstractEnvironment implements ConfigurableEnvironment {
      private final MutablePropertySources propertySources = new MutablePropertySources(this.logger);
      //PropertyResolver : Environment的顶层接口,主要提供属性检索和解析带占位符的文本。
      private final ConfigurablePropertyResolver propertyResolver =
            new PropertySourcesPropertyResolver(this.propertySources);
      public AbstractEnvironment() {
                //这个抽象方法在StandardEnvironment中实现
        customizePropertySources(this.propertySources);
        if (this.logger.isDebugEnabled()) {
            this.logger.debug(format(
                    "Initialized %s with PropertySources %s", getClass().getSimpleName(), this.propertySources));
        }
    }
    }

StandardEnvironment中实现抽象方法:

        @Override
    protected void customizePropertySources(MutablePropertySources propertySources) {
        propertySources.addLast(new MapPropertySource(SYSTEM_PROPERTIES_PROPERTY_SOURCE_NAME, getSystemProperties()));
        propertySources.addLast(new SystemEnvironmentPropertySource(SYSTEM_ENVIRONMENT_PROPERTY_SOURCE_NAME, getSystemEnvironment()));
    }

getSystemProperties():

    try {
        return (Map) System.getProperties();
        }catch (AccessControlException ex) {
                ...}

###1.2.2 Properties接口 System.getProperties():

private static Properties props;
public static Properties getProperties() {
        //首先经过安全管理器的检查
        SecurityManager sm = getSecurityManager();
        if (sm != null) {
            sm.checkPropertiesAccess();
        }
        return props;
    }

Properties类:

public
class Properties extends Hashtable<Object,Object> {
      public synchronized Object setProperty(String key, String value) {
        return put(key, value);
    }
    public String getProperty(String key) {
        Object oval = super.get(key);
        String sval = (oval instanceof String) ? (String)oval : null;
        return ((sval == null) && (defaults != null)) ? defaults.getProperty(key) : sval;
    }
}

由此段代码可以看出Properties继承于Hashtable,以键值对的方式实现。

  • 回到上面的路径解析问题: this.getEnvironment().resolveRequiredPlaceholders(path)就是启动了AbstractEnvironment.resolveRequiredPlaceholders:
@Override
    public String resolveRequiredPlaceholders(String text) throws IllegalArgumentException {
        return this.propertyResolver.resolveRequiredPlaceholders(text);
    }

进而启动AbstractEnvironment.propertyResolver.resolveRequiredPlaceholders(text),而AbstractEnvironment.propertyResolver:

private final ConfigurablePropertyResolver propertyResolver =
            new PropertySourcesPropertyResolver(this.propertySources);

PropertySourcesPropertyResolver继承于AbstractPropertyResolver,则最终触发AbstractPropertyResolver.resolveRequiredPlaceholders(String text):

@Override
    public String resolveRequiredPlaceholders(String text) throws IllegalArgumentException {
                //初始化占位符解析器
        if (this.strictHelper == null) {
            this.strictHelper = createPlaceholderHelper(false);
        }
                //调用doResolvePlaceholders,进行替换占位符具体值
        return doResolvePlaceholders(text, this.strictHelper);
    }

private String doResolvePlaceholders(String text, PropertyPlaceholderHelper helper) {
                //替换占位符具体值
        return helper.replacePlaceholders(text, new PropertyPlaceholderHelper.PlaceholderResolver() {
            @Override
            public String resolvePlaceholder(String placeholderName) {
                                //通过key获取占位符对应的String类型具体值
                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>());
    }

###1.3 refresh AbstractApplicationContext中的refresh()方法是spring初始化中的核心方法,在创建IoC容器前,如果已经有容器存在,则需要把已有的容器销毁和关闭,以保证在refresh之后使用的是新建立起来的IoC容器。 AbstractApplicationContext.refresh():

@Override
    public void refresh() throws BeansException, IllegalStateException {
        synchronized (this.startupShutdownMonitor) {
            // 设置启动时间,是否激活标识位,初始化属性源(property source)配置
            prepareRefresh();

            // 创建beanFactory(过程是根据xml为每个bean生成BeanDefinition并注册到生成的beanFactory)
            ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

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

            try {
                // Allows post-processing of the bean factory in context subclasses.
                postProcessBeanFactory(beanFactory);

                // Invoke factory processors registered as beans in the context.
                invokeBeanFactoryPostProcessors(beanFactory);

                // Register bean processors that intercept bean creation.
                registerBeanPostProcessors(beanFactory);

                // Initialize message source for this context.
                initMessageSource();

                // Initialize event multicaster for this context.
                initApplicationEventMulticaster();

                // Initialize other special beans in specific context subclasses.
                onRefresh();

                // Check for listener beans and register them.
                registerListeners();

                // Instantiate all remaining (non-lazy-init) singletons.
                finishBeanFactoryInitialization(beanFactory);

                // Last step: publish corresponding event.
                finishRefresh();
            }

            catch (BeansException ex) {
                logger.warn("Exception encountered during context initialization - cancelling refresh attempt", ex);

                // Destroy already created singletons to avoid dangling resources.
                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();
            }
        }
    }

####加载类 obtainFreshBeanFactory()方法实现了类的装载,AbstractApplicationContext的obtainFreshBeanFactory()方法调用子类AbstractRefreshableApplicationContext的refreshBeanFactory()方法,启动容器载入Bean定义资源文件的过程: AbstractApplicationContext.obtainFreshBeanFactory():

    protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
        refreshBeanFactory();
        ConfigurableListableBeanFactory beanFactory = getBeanFactory();
        if (logger.isDebugEnabled()) {
            logger.debug("Bean factory for " + getDisplayName() + ": " + beanFactory);
        }
        return beanFactory;
    }

AbstractRefreshableApplicationContext.refreshBeanFactory():

@Override
    protected final void refreshBeanFactory() throws BeansException {
        //从这里可以看出,如果存在容器则销毁并关闭
        if (hasBeanFactory()) {
            destroyBeans();
            closeBeanFactory();
        }
        try {
            //new出一个新的DefaultListableBeanFactory作为IoC容器
            DefaultListableBeanFactory beanFactory = createBeanFactory();
            beanFactory.setSerializationId(getId());
            //对IoC容器进行定制化,如设置启动参数,开启注解的自动装配等
            customizeBeanFactory(beanFactory);
            //调用载入Bean定义的方法,主要这里又使用了一个委派模式,在当前类中只定义了抽象的loadBeanDefinitions方法,具体的实现调用子类容器(AbstractXmlApplicationContext)
            loadBeanDefinitions(beanFactory);
            synchronized (this.beanFactoryMonitor) {
                this.beanFactory = beanFactory;
            }
        }
        catch (IOException ex) {
            throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex);
        }
    }

AbstractXmlApplicationContext.loadBeanDefinitions(beanFactory):

    @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.
        beanDefinitionReader.setEnvironment(this.getEnvironment());
        beanDefinitionReader.setResourceLoader(this);
        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);
    }

文章永久链接:https://tech.souyunku.com/42545

未经允许不得转载:搜云库技术团队 » Spring

JetBrains 全家桶,激活、破解、教程

提供 JetBrains 全家桶激活码、注册码、破解补丁下载及详细激活教程,支持 IntelliJ IDEA、PyCharm、WebStorm 等工具的永久激活。无论是破解教程,还是最新激活码,均可免费获得,帮助开发者解决常见激活问题,确保轻松破解并快速使用 JetBrains 软件。获取免费的破解补丁和激活码,快速解决激活难题,全面覆盖 2024/2025 版本!

联系我们联系我们