Spring源码阅读

① 定位:定位资源文件(定位配置文件或扫描相关注解)

② 加载:解析配置信息

③ 注册:将Bean的信息表示解析成BeanDefinition注册到BeanDefinitionMap

ClassPathXmlApplicationContext:

  1. 初始化资源加载器:AbstractApplicationContext()
// AbstractApplicationContext类
	public AbstractApplicationContext() {
		this.resourcePatternResolver = getResourcePatternResolver();
	}
	
	//获取一个Spring Source的加载器用于读入Spring Bean定义资源文件
	protected ResourcePatternResolver getResourcePatternResolver() {
		//AbstractApplicationContext继承DefaultResourceLoader,因此也是一个资源加载器
		return new PathMatchingResourcePatternResolver(this);
	}
  1. 设置资源路径:setConfigLocations(configLocations);

  2. 容器初始化AbstractApplicationContext#refresh()

   // ClassPathXmlApplicationContext类
   public ClassPathXmlApplicationContext(
       String[] configLocations, boolean refresh, @Nullable ApplicationContext parent)      throws BeansException {
       // IOC 1:初始化资源加载器   
       super(parent);   
       // IOC 2: 设置资源路径   
       setConfigLocations(configLocations);      
       if (refresh) {      
           // IOC 3:IOC容器初始化入口,重启、刷新、重置、相关组件初始化
           // AbstractApplicationContext#refresh()
           refresh();   
       }}
  • 刷新bean factory:AbstractRefreshableApplicationContext#refreshBeanFactory()
AbstractApplicationContext#refresh():
    ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
AbstractApplicationContext#obtainFreshBeanFactory():
    refreshBeanFactory();

// AbstractRefreshableApplicationContext#refreshBeanFactory()
	@Override
	protected final void refreshBeanFactory() throws BeansException {
		// IOC : 如果已经有容器,销毁容器中的bean,关闭容器
		if (hasBeanFactory()) {
			destroyBeans();
			closeBeanFactory();
		}
		try {
			// IOC :创建IOC容器
			DefaultListableBeanFactory beanFactory = createBeanFactory();
			beanFactory.setSerializationId(getId());
			// 对IOC容器进行定制化,如设置启动参数,开启注解的自动装配等
			customizeBeanFactory(beanFactory);
			
			// IOC 5:开始加载BeanDefinitions.(由具体子类实现)
			loadBeanDefinitions(beanFactory);
			synchronized (this.beanFactoryMonitor) {
				this.beanFactory = beanFactory;
			}
		}
		catch (IOException ex) {
			throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex);
		}
	}
  • 加载BeanDefinitions(子类实现):AbstractXmlApplicationContext#loadBeanDefinitions()
// AbstractXmlApplicationContext#loadBeanDefinitions()
protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) 
    throws BeansException, IOException {
		// IOC : 创建XmlBeanDefinitionReader,即创建Bean读取器,并通过回调设置到容器中去,容器使用该读取器读取Bean定义资源
		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);

		// IOC 6 : Bean读取器真正实现加载的方法
		loadBeanDefinitions(beanDefinitionReader);
	}

// AbstractXmlApplicationContext#loadBeanDefinitions()
protected void loadBeanDefinitions(XmlBeanDefinitionReader reader) 
    throws BeansException, IOException {
		// 获取资源定位
		Resource[] configResources = getConfigResources();
		if (configResources != null) {
			// IOC 7: Xml读取器调用其父类AbstractBeanDefinitionReader读取定位的Bean定义资源
			reader.loadBeanDefinitions(configResources);
		}
		
        // 获取FileSystemXmlApplicationContext构造方法中setConfigLocations方法设置的资源
		String[] configLocations = getConfigLocations();
		if (configLocations != null) {
			reader.loadBeanDefinitions(configLocations);
		}
	}

// IOC : 遍历加载
AbstractBeanDefinitionReader#loadBeanDefinitions():
	  counter += loadBeanDefinitions(location);

public int loadBeanDefinitions(EncodedResource encodedResource) 
    throws BeanDefinitionStoreException {
		try {
			// IOC :将资源文件转为InputStream的IO流
			InputStream inputStream = encodedResource.getResource().getInputStream();
			try {
				InputSource inputSource = new InputSource(inputStream);
				if (encodedResource.getEncoding() != null) {
					inputSource.setEncoding(encodedResource.getEncoding());
				}
				// IOC 8 : 具体解析资源文件
				return doLoadBeanDefinitions(inputSource, encodedResource.getResource());
			}
			finally {
				//关闭从Resource中得到的IO流
				inputStream.close();
			}
		}
    }
  • 解析资源文件,并注册到BeanDefinitionMap:XmlBeanDefinitionReader#doLoadBeanDefinitions()
// XmlBeanDefinitionReader#doLoadBeanDefinitions()
protected int doLoadBeanDefinitions(InputSource inputSource, Resource resource)
	throws BeanDefinitionStoreException {
		try {
			// IOC : 将XML文件转换为DOM对象,解析过程由documentLoader实现
			Document doc = doLoadDocument(inputSource, resource);
			// IOC 9: 这里是启动对Bean定义解析的详细过程,该解析过程会用到Spring的Bean配置规则
			return registerBeanDefinitions(doc, resource);
		}catch(Exception ex){
            // ...
        }
}

//按照Spring的Bean语义要求将Bean定义资源解析并转换为容器内部数据结构
public int registerBeanDefinitions(Document doc, Resource resource) 
    throws BeanDefinitionStoreException {
		//得到BeanDefinitionDocumentReader来对xml格式的BeanDefinition解析
		BeanDefinitionDocumentReader documentReader = createBeanDefinitionDocumentReader();
		//获得容器中注册的Bean数量
		int countBefore = getRegistry().getBeanDefinitionCount();

		// IOC 10:具体的解析实现过程由实现类DefaultBeanDefinitionDocumentReader完成
		documentReader.registerBeanDefinitions(doc, createReaderContext(resource));
		//统计解析的Bean数量
		return getRegistry().getBeanDefinitionCount() - countBefore;
	}

// IOC 11:解析并注册BeanDefinitions
DefaultBeanDefinitionDocumentReader#registerBeanDefinitions():
	  doRegisterBeanDefinitions(root);

// IOC 12 : 从根元素开始对Document元素进行解析,
 DefaultBeanDefinitionDocumentReader#doRegisterBeanDefinitions():
	  parseBeanDefinitions(root, this.delegate);
 DefaultBeanDefinitionDocumentReader#parseBeanDefinitions():
	  parseDefaultElement(ele, delegate);

// IOC 13: 元素节点既不是导入元素,也不是别名元素,即普通的<Bean>元素
DefaultBeanDefinitionDocumentReader#parseDefaultElement():
	else if (delegate.nodeNameEquals(ele, BEAN_ELEMENT)) {
		processBeanDefinition(ele, delegate);}

//DefaultBeanDefinitionDocumentReader#processBeanDefinition():
protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) {
		// BeanDefinitionHolder是对BeanDefinition的封装,即Bean定义的封装类
    	// IOC 14:将解析出的beanName和beanDefinition封装成Holder。
		BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);
		if (bdHolder != null) {
			bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder);
			try {
				// IOC 15:向Spring IOC容器注册解析得到的Bean定义
				BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry());
			}
			catch (BeanDefinitionStoreException ex) {
				getReaderContext().error("Failed to register bean definition with name '" +
						bdHolder.getBeanName() + "'", ele, ex);
			}

			//在完成向Spring IOC容器注册解析得到的Bean定义之后,发送注册事件
			getReaderContext().fireComponentRegistered(new BeanComponentDefinition(bdHolder));
		}
	}

AnnotationConfigApplicationContext

  1. 初始化注解Bean读取器和包路径扫描器:AnnotationConfigApplicationContext()
public AnnotationConfigApplicationContext() {   
    this.reader = new AnnotatedBeanDefinitionReader(this);   
    this.scanner = new ClassPathBeanDefinitionScanner(this);
}

public AnnotationConfigApplicationContext(Class<?>... annotatedClasses) {
	// IOC 1 : 初始化注解Bean读取器和包路径扫描器
    this();
	// IOC 2 :直接注册beanDefinition到容器中
	register(annotatedClasses);
    // IOC 3 :刷新容器
	refresh();
}

public AnnotationConfigApplicationContext(String... basePackages) {
	this();
	// IOC 2 :设置扫描包路径,将包路径下的所有Bean对象注册到容器中
	scan(basePackages);
	refresh();
}
  • 直接注册:register(Class<?>... annotatedClasses)
// IOC 2 :为容器注册一个要被处理的注解Bean,必须手动调用容器的refresh()方法刷新容器,触发容器对新注册的Bean的处理
public void register(Class<?>... annotatedClasses) {   
    Assert.notEmpty(annotatedClasses, "At least one annotated class must be specified");     this.reader.register(annotatedClasses);
}
  • 设置扫描路径:scan(String... basePackages)
// IOC 2 :扫描指定包路径及其子包下的注解类,为了使新添加的类被处理,必须手动调用refresh()方法刷新容器
public void scan(String... basePackages) {   
	Assert.notEmpty(basePackages, "At least one base package must be specified");   		this.scanner.scan(basePackages);
}
原文地址:https://www.cnblogs.com/kiqi/p/14346756.html