Spring3.1.1浅析(一)

首先了解一下spring的启动细节:

1、创建maven工程,pom文件中加入对spring的依赖和log4j的支持:

2、建立两个测试类,其中service中包含对dao的引用,然后定义一个Test类进行测试用:




3、配置文件中配置dao和service:


Log4J.properties:

log4j.rootCategory=INFO,stdout

log4j.appender.stdout=org.apache.log4j.ConsoleAppender

log4j.appender.stdout.layout=org.apache.log4j.PatternLayout

log4j.appender.stdout.layout.ConversionPattern=%d{ABSOLUTE}%5p%t%c{2}:%L-%m%n

log4j.category.org.springframework.beans.factory=DEBUG

运行结果如下:

可见我们成功调用了ServiceFoodoSomething方法,下面我们看一下spring在这期间究竟做了什么:

1、刷新org.springframework.context.support.ClassPathXmlApplicationContext对象,因为我们用的是ClassPathXmlApplicationContext这种方式创建ApplicationContext,所以spring启动后先调用这个类进行初始化。

那么 ClassPathXmlApplicationContext 这个类干了些什么工作呢,我们打开源码:

可见,这个类就是根据location指定的位置读取xml文件,真正的读取方法是它的父类AbstractXmlApplicationContext中定义的,代码如下:


传入的参数就是DefaultListableBeanFactory,这应该是spring的默认beanFactory,然后初始化一个用来读取xml,首先设置了一下它要做的一件事就是先解析出DefaultListableBeanFactory中的资源列表,然后一个一个读取:



loadBeanDefinitions首先指定ResourceEncoding方式,并把它们放在EncodedResource对象中,接着调用读取的方法:


接下来我们断点调试一下这个方法,看看其中有什么奥秘,第一行首先读入的是class path resource [services.xml]这个配置,resourcesCurrentlyBeingLoaded这个是个ThreadLocal<Set<EncodedResource>>,也就是是个线程绑定的集合,集合中防入了EncodedResource对象,这个我们在上文中也提到过就是编码和Resource的封装对象,然后是这个集合的初始化工作,这个不用解释了,执行到这个代码时就开始读取services.xml这个文件了。

这个方法时实际解析bean定义的方法,我们看一下这个方法:


documentLoader.loadDocument方法读取了services.xml的内容并得到Document对象,当然了还有些附件操作,如格式验证,命名空间验证等。


这个方法根据刚才生成的Document对象解析bean的定义,registerBeanDefinitions除了Document之外另一个参数是ReaderContext,这个我的理解是一个和命令空间有关的XmlReaderContext对象,也就是说可能不同的命名空间下有同名的xmlReader对象,这个就是区分的作用。

说了这么多总要开始解析了吧,

这个也是一个很重要的方法,其中BeanDefinitionParserDelegate对象是个bean定义的代理类,

preProcessXml(root);postProcessXml(root);

目前是这个接口中声明的方法,没有具体实现,作用就是可以在解析xmlbean之前和之后进行一些回调操作。

parseBeanDefinitions解析终于开始了:

parseDefaultElement 进行默认的解析:


定义了四种解析的方式:解析import标签、beans标签、bean标签和alias标签。其中 BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder,getReaderContext().getRegistry());

这个方法时核心方法,就是把解析到的bean注册到容器中:


beanName:得到serviceFoo

definitionHolder:保留了bean的属性信息:

Bean definition withname 'serviceFoo' and aliases []: Generic bean: class[com.yushh.test.chapter42.ServiceFoo]; scope=; abstract=false; lazyInit=false;autowireMode=0; dependencyCheck=0; autowireCandidate=true; primary=false;factoryBeanName=null; factoryMethodName=null; initMethodName=null;destroyMethodName=null; defined in class path resource [services.xml]

至此完成了对一个bean的解析。

下面我们总结一下: spring 通过 ClassPathXmlApplicationContext 类的 loadBeanDefinitions 完成对 bean 的解析。后者通过调用 XmlBeanDefinitionReader doLoadBeanDefinitions 生成要解析的 Document 对象,然后调用 BeanDefinitionDocumentReader 的实现类 DefaultBeanDefinitionDocumentReader doRegisterBeanDefinitions 方法进行真正的解析,最后把解析到的 bean 通过 BeanDefinitionReaderUtils 注册到容器中。

你可能感兴趣的:(Spring3)