Spring源码学习(三)—spring-Beans(1)

    从这篇起,正式开始对spring源码的阅读和学习。根据书上的流程,先对spring核心容器模块中的Beans模块下手。对于beans包来说,有两个非常核心的类,第一个是DefaultListableBeanFactory,该类实现默认的对bean的注册和加载,这也是控制反转特性的最基本的功能,第二个类是XmlBeanDefinitionReader,该类提供了spring的IOC容器中对xml格式的配置文件的读取、解析和注册。先写个小Demo。

TestBeanFactory.java

import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.xml.XmlBeanFactory;
import org.springframework.core.io.ClassPathResource;

import springDemo.bean.TestBean;

@SuppressWarnings("deprecation")
public class TestBeanFactory {
	public static void testDemo() {
		BeanFactory bf = new XmlBeanFactory(new ClassPathResource("spring-Config.xml"));
		TestBean tb = (TestBean) bf.getBean("testBean");
		System.out.println(tb.getTestString());
	}

	public static void main(String[] args) {
		testDemo();
		System.exit(0);
	}
}

TestBean.java

package springDemo.bean;

public class TestBean {
	private String testString = "Test,Testing!!";

	public String getTestString() {
		return testString;
	}

	public void setTestString(String testString) {
		this.testString = testString;
	}

}

spring-config.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd">
    <bean id="testBean" class="springDemo.bean.TestBean">
    </bean>
</beans>

     上面的Demo是一个最基本的spring使用例子。我们就从这个Demo开始分析spring-Beans源码的运作原理。这个Demo主要完成了三个工作:1.首先获取一个ioc容器,也就是实现一个beanFactory并告诉容器配置文件在哪旮沓;2.其次,找容器把配置文件中注册的bean的实例要过来;3.调用bean中的方法证明老子自己不创建对象照样能用它!

    看第一步的代码

  

BeanFactory bf = new XmlBeanFactory(new ClassPathResource("spring-Config.xml"));  

    这一步创建了一个XmlBeanFactory对象,这个类是IOC容器的核心类之一,继承自DefaultListableBeanFactory,类图如下:


    DefaultListableBeanFactory继承自AbstractAutowireCapableBeanFactory,这个类主要实现bean的创建、自动注入、初始化等功能。同时,DefaultListableBeanFactory还实现了ConfigurableListableBeanFactory、BeanDefinitionRegistry和Serializable三个接口,这三个接口的功能分别是提供配置Factory的各种方法、定义对BeanDefinition的各种操作和序列化。XMLBeanFactory在此基础上,增加了对xml格式文件的读取和解析的功能。打断点往里面走:

  1.首先程序进入DefaultSingletonBeanRegistry类中,为什么会调用到该类呢,从类图中可以看出,DefaultStringletonBeanRegistry是XMLBeanFactory的爷爷的爷爷类,根据jvm的类加载顺序,即先父类再子类,然后父类的静态方法,子类的静态方法,父类的静态代码块,子类的静态代码块,父类的构造方法和子类的构造方法;在DefaultStringletonBeanRegistry中有一个静态变量 NULL_OBJECT,由于该类主要实现了单例bean的注册,单例bean即IOC容器只持有一个bean的实例,通过其中维护的三个map作为缓存对IOC容器中注册的单例bean进行存储,由于concurrentHashMap无法存储null值,因此实现静态变量NULL_OBJECT来解决这个问题;

    2.接着走,到了加载XMLBeanFactory的父类DefaultListableBeanFactory了,这里有个静态代码块:

private static Class<?> javaxInjectProviderClass = null;

	static {
		try {
			javaxInjectProviderClass =
					ClassUtils.forName("javax.inject.Provider", DefaultListableBeanFactory.class.getClassLoader());
		}
		catch (ClassNotFoundException ex) {
			// JSR-330 API not available - Provider interface simply not supported then.
		}
	}    
这里获取到javaxInjectProviderClass的类名,javax.inject.provider<T>是对类T的依赖注入接口,至于文档中解释的它的功能我现在还搞不懂,就先不展示了;值得一提的是,在对这个类进行动态加载的时候,调用的是ClassUtils.forName(String name, ClassLoader classLoader)方法,下一篇先对这个方法好好研究研究。

猜你喜欢

转载自blog.csdn.net/qq_21399231/article/details/80656119