亲宝软件园·资讯

展开

SpringFramework之IoC容器初始化

码头工人 人气:1
## 分析例子 #### 启动类 Application,使用的是ClassPathXmlApplicationContext来加载xml文件 ```java /** * @author jianw.li * @date 2020/3/16 11:53 PM * @Description: TODO */ public class MyApplication { private static final String CONFIG_LOCATION = "classpath:application_context.xml"; private static final String BEAN_NAME = "hello"; public static void main(String[] args) { ApplicationContext ac = new ClassPathXmlApplicationContext(CONFIG_LOCATION); Hello hello = (Hello) ac.getBean(BEAN_NAME); hello.sayHello(); } } ``` #### Bean ```java /** * @author jianw.li * @date 2020/3/16 11:53 PM * @Description: TODO */ public class Hello { public void sayHello() { System.out.println("Hello World"); } } ``` #### 配置文件 ​ 在resources下建立名为classpath:application_context.xml的配置文件,并配置好Bean ```xml ``` ## 总体结构 ​ **ClassPathXmlApplicationContext继承体系如下:** ![KWJf7l](https://gitee.com/leeboyce/imagebed/raw/20200305-image/uPic/KWJf7l.png) ​ **IoC总体结构图如下:** ![image-20200322155805716](/Users/lijianwei/Library/Application Support/typora-user-images/image-20200322155805716.png) ## 源码分析 #### ClassPathXmlApplicationContext ```java //构造函数,创建ClassPathXmlApplicationContext,其中configLocation为Bean所在的文件路径 public ClassPathXmlApplicationContext(String configLocation) throws BeansException { this(new String[] {configLocation}, true, null); } public ClassPathXmlApplicationContext( String[] configLocations, boolean refresh, @Nullable ApplicationContext parent) throws BeansException { //null super(parent); //设置配置路径至ApplicationContext中 setConfigLocations(configLocations); if (refresh) { //核心方法,refresh会将旧的ApplicaionContext销毁 refresh(); } } ``` #### AbstractApplicationContext ##### refresh ​ 核心方法,refresh销毁旧ApplicationContext,生成新的ApplicationContext ```java @Override public void refresh() throws BeansException, IllegalStateException { //加锁.没有明确对象,只是想让一段代码同步,可以创建Object startupShutdownMonitor = new Object() synchronized (this.startupShutdownMonitor) { // 为context刷新准备.设置启动时间,设置激活状态等 prepareRefresh(); // 告知子类刷新内部bean factory. 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) { if (logger.isWarnEnabled()) { 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 ​ 告知子类刷新内部bean factory. ​ 核心方法,初始化BeanFactory、加载Bean、注册Bean ```java protected ConfigurableListableBeanFactory obtainFreshBeanFactory() { //刷新Bean工厂,关闭并销毁旧BeanFacroty refreshBeanFactory(); ConfigurableListableBeanFactory beanFactory = getBeanFactory(); if (logger.isDebugEnabled()) { logger.debug("Bean factory for " + getDisplayName() + ": " + beanFactory); } return beanFactory; } ``` ##### refreshBeanFactory ​ 关闭并销毁旧BeanFactory,创建与初始化新BeanFactory。**为什么是DefaultListableBeanFactory?** ```java @Override protected final void refreshBeanFactory() throws BeansException { if (hasBeanFactory()) { destroyBeans(); closeBeanFactory(); } try { //初始化DefaultListableBeanFactory,为什么选择实例化DefaultListableBeanFactory?而不是其他的Bean工厂 DefaultListableBeanFactory beanFactory = createBeanFactory(); //Bean工厂序列化设置id beanFactory.setSerializationId(getId()); //定制Bean工厂,设置不允许覆盖Bean,不允许循环依赖等 customizeBeanFactory(beanFactory); //将Bean加载至Bean工厂中 loadBeanDefinitions(beanFactory); //此处synchronized块与#hasBeanFactory中的synchronized块存在关联,此处锁住之后hasBeanFactory中的synchronized块将等待 //避免beanFactory未销毁或未关闭的情况 synchronized (this.beanFactoryMonitor) { this.beanFactory = beanFactory; } } catch (IOException ex) { throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex); } } ``` ##### customizeBeanFactory ​ 定制BeanFactory。设置Bean覆盖、循环依赖等。**什么是循环依赖?** ``` protected void customizeBeanFactory(DefaultListableBeanFactory beanFactory) { if (this.allowBeanDefinitionOverriding != null) { //默认值为false不允许对Bean进行覆盖 beanFactory.setAllowBeanDefinitionOverriding(this.allowBeanDefinitionOverriding); } if (this.allowCircularReferences != null) { //默认值为false,不允许循环依赖 beanFactory.setAllowCircularReferences(this.allowCircularReferences); } } ``` #### AbstractXmlApplicationContext ##### loadBeanDefinitions ```java @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); } ``` ##### loadBeanDefinitions ```java protected void loadBeanDefinitions(XmlBeanDefinitionReader reader) throws BeansException, IOException { Resource[] configResources = getConfigResources(); if (configResources != null) { //加载资源对象,最终还是会回到这种方式去加载bean. reader.loadBeanDefinitions(configResources); } String[] configLocations = getConfigLocations(); if (configLocations != null) { //加载资源路径吗 reader.loadBeanDefinitions(configLocations); } } ``` #### AbstractBeanDefinitionReader ##### loadBeanDefinitions ```java @Override public int loadBeanDefinitions(String... locations) throws BeanDefinitionStoreException { Assert.notNull(locations, "Location array must not be null"); int counter = 0; //循环配置文件路径 for (String location : locations) { counter += loadBeanDefinitions(location); } return counter; } ``` ```java public int loadBeanDefinitions(String location, @Nullable Set

加载全部内容

相关教程
猜你喜欢
用户评论