spring framework 4 源码阅读(2)---从ClassPathXmlApplicationContext开始

Application初始化日志

15:23:12.790 [main] DEBUG o.s.core.env.StandardEnvironment - Adding [systemProperties] PropertySource with lowest search precedence
15:23:12.797 [main] DEBUG o.s.core.env.StandardEnvironment - Adding [systemEnvironment] PropertySource with lowest search precedence
15:23:12.797 [main] DEBUG o.s.core.env.StandardEnvironment - Initialized StandardEnvironment with PropertySources [systemProperties,systemEnvironment]
//初始化Environment
15:23:12.803 [main] INFO  o.s.c.s.ClassPathXmlApplicationContext - Refreshing org[email protected]480a6370: startup date [Mon Aug 25 15:23:12 CST 2014]; root of context hierarchy
15:23:12.861 [main] DEBUG o.s.core.env.StandardEnvironment - Adding [systemProperties] PropertySource with lowest search precedence
15:23:12.862 [main] DEBUG o.s.core.env.StandardEnvironment - Adding [systemEnvironment] PropertySource with lowest search precedence
15:23:12.862 [main] DEBUG o.s.core.env.StandardEnvironment - Initialized StandardEnvironment with PropertySources [systemProperties,systemEnvironment]
//读取XML
15:23:12.880 [main] INFO  o.s.b.f.xml.XmlBeanDefinitionReader - Loading XML bean definitions from class path resource [simpleContext.xml]
15:23:12.885 [main] DEBUG o.s.b.f.xml.DefaultDocumentLoader - Using JAXP provider [com.sun.org.apache.xerces.internal.jaxp.DocumentBuilderFactoryImpl]
15:23:12.928 [main] DEBUG o.s.b.factory.xml.BeansDtdResolver - Found beans DTD [http://www.springframework.org/dtd/spring-beans-2.0.dtd] in classpath: spring-beans-2.0.dtd
//读取BeanDefinition
15:23:12.953 [main] DEBUG o.s.b.f.x.DefaultBeanDefinitionDocumentReader - Loading bean definitions
//解析XML
15:23:12.971 [main] DEBUG o.s.b.f.x.BeanDefinitionParserDelegate - No XML 'id' specified - using 'simpleBean' as bean name and [] as aliases
15:23:12.986 [main] DEBUG o.s.b.f.x.BeanDefinitionParserDelegate - No XML 'id' specified - using 'anotherBean' as bean name and [] as aliases
15:23:12.986 [main] DEBUG o.s.b.f.xml.XmlBeanDefinitionReader - Loaded 3 bean definitions from location pattern [simpleContext.xml]
//将获取到的BeanDefined设置到BeanFactory中
15:23:12.987 [main] DEBUG o.s.c.s.ClassPathXmlApplicationContext - Bean factory for org[email protected]480a6370: org.s[email protected]74bdaaa: defining beans [simpleBean,property,anotherBean]; root of factory hierarchy
//初始化MessageSource,I18N中使用
15:23:13.025 [main] DEBUG o.s.c.s.ClassPathXmlApplicationContext - Unable to locate MessageSource with name 'messageSource': using default [[email protected]6c5f]
//application事件中心
15:23:13.029 [main] DEBUG o.s.c.s.ClassPathXmlApplicationContext - Unable to locate ApplicationEventMulticaster with name 'applicationEventMulticaster': using default [org.[email protected]5629fbc9]

一些bean的初始化

一个简单的bean,里面有个属性property,以及test方法和需要进行属性注入的setProperty

/**
 * 基本的bean方便测试
 * Created by zhangya on 2014/8/13.
 */
public class SimpleBean
{
	private static final Logger LOGGER = LoggerFactory.getLogger(SimpleBean.class);
	private SimpleBeanProperty property;

	/**
	 * 简单测试方法
	 */
	public void test()
	{
		LOGGER.info("SimpleBean is loading.");
		property.propertyTest();
	}

	/**
	 * 设置属性 property
	 * <p>记录日志
	 * @param property
	 */
	public void setProperty(SimpleBeanProperty property)
	{
		LOGGER.info("Property is setting.");
		this.property = property;
	}
}

作为属性赋值的bean,里面包含初始化方法

/**
 * 作为属性初始化的bean
 * Created by zhangya on 2014/8/13.
 */
public class SimpleBeanProperty
{
	private static final Logger LOGGER = LoggerFactory.getLogger(SimpleBeanProperty.class);
	private String simpleVariable = "test567";
	public SimpleBeanProperty()
	{
		LOGGER.info("SimpleBeanProperty is loading.");
	}

	/**
	 * property的test方法
	 */
	public void propertyTest()
	{
		LOGGER.info("propertyTest method is invoking.{}",this);
	}

	/**
	 * 设置变量
	 * @param simpleVariable
	 */
	public void setSimpleVariable(String simpleVariable)
	{
		this.simpleVariable = simpleVariable;
	}

	/**
	 * 获取变量的值
	 * @return 变量的值
	 */
	public String getSimpleVariable()
	{
		return simpleVariable;
	}

	@Override
	public String toString()
	{
		return "SimpleBeanProperty{" +
				"simpleVariable='" + simpleVariable + '\'' +
				'}';
	}
}

另外一个

/**
 * 用于初始化的另外一个bean
 * @author zhangya
 * @category com.letume.spring.study.init
 * @since 2014/8/24
 */
public class SimpleAnotherBean
{
	private static final Logger LOGGER = LoggerFactory.getLogger(SimpleBeanProperty.class);
	private String simpleVariable = "test123";

	public SimpleAnotherBean()
	{
		LOGGER.info("SimpleAnotherBean is loading.");
	}

	/**
	 * property的test方法
	 */
	public void test()
	{
		LOGGER.info("test method is invoking.{}",this);
	}

	/**
	 * 设置变量
	 * @param simpleVariable
	 */
	public void setSimpleVariable(String simpleVariable)
	{
		this.simpleVariable = simpleVariable;
	}

	@Override
	public String toString()
	{
		return "SimpleAnotherBean{" +
				"simpleVariable='" + simpleVariable + '\'' +
				'}';
	}
}

simpleContext.xml applicationContext的配置文件,这里使用xml形式对bean进行配置

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN 2.0//EN"
        "http://www.springframework.org/dtd/spring-beans-2.0.dtd">
<beans>
    <bean name="simpleBean"
          class="com.letume.spring.study.init.SimpleBean">
        <property name="property"><ref local="property"/> </property>
    </bean>
    <bean id="property" name="property"
          class="com.letume.spring.study.init.SimpleBeanProperty" scope="prototype"/>
    <bean name="anotherBean"
          class="com.letume.spring.study.init.SimpleAnotherBean" scope="prototype"/>
</beans>

下面是main函数,

例1 普通的bean初始化调用过程

/**
 * 简单的spring类加载的方法
 * <pre>
 * ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(PATH+RESOURCE_CONTEXT);
 * SimpleBean simpleBean = context.getBean(SimpleBean.class)
 * simpleLoaderSimpleBean.test();
 * </pre>
 * Created by mitchz on 2014/8/13.
 */
public class SimpleInit
{

	private static final String PATH = "";
	private static final String RESOURCE_CONTEXT = "simpleContext.xml";

	public static void main(String[] args) throws InterruptedException
	{
		ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(
				PATH + RESOURCE_CONTEXT);
		//获取simpleBean
		SimpleBean simpleBean = context
				.getBean("simpleBean", SimpleBean.class);
		simpleBean.test();
		//context.registerShutdownHook();
	}
}

看下日志:

---执行单例的初始化(为什么会使用单例)
14:36:48.766 [main] DEBUG o.s.b.f.s.DefaultListableBeanFactory - Pre-instantiating singletons in org.s[email protected]29d8a2c5: defining beans [simpleBean,property,anotherBean]; root of factory hierarchy
14:36:48.767 [main] DEBUG o.s.b.f.s.DefaultListableBeanFactory - Creating shared instance of singleton bean 'simpleBean'
---创建bean实例
14:36:48.767 [main] DEBUG o.s.b.f.s.DefaultListableBeanFactory - Creating instance of bean 'simpleBean'
14:36:48.786 [main] DEBUG o.s.b.f.s.DefaultListableBeanFactory - Eagerly caching bean 'simpleBean' to allow for resolving potential circular references
---创建属性的实例
14:36:48.799 [main] DEBUG o.s.b.f.s.DefaultListableBeanFactory - Creating instance of bean 'property'
14:36:48.799 [main] INFO  c.l.s.study.init.SimpleBeanProperty - SimpleBeanProperty is loading.
14:36:48.799 [main] DEBUG o.s.b.f.s.DefaultListableBeanFactory - Finished creating instance of bean 'property'
---赋值
14:36:48.838 [main] INFO  c.l.spring.study.init.SimpleBean - Property is setting.
14:36:48.840 [main] DEBUG o.s.b.f.s.DefaultListableBeanFactory - Finished creating instance of bean 'simpleBean'

....

---getBean的方法执行时,则直接从cache中取,之前初始化的实例
14:36:48.847 [main] DEBUG o.s.b.f.s.DefaultListableBeanFactory - Returning cached instance of singleton bean 'simpleBean'
14:36:48.847 [main] INFO  c.l.spring.study.init.SimpleBean - SimpleBean is loading.SimpleBean{property=SimpleBeanProperty{simpleVariable='test567'}}
14:36:48.849 [main] INFO  c.l.s.study.init.SimpleBeanProperty - propertyTest method is invoking.SimpleBeanProperty{simpleVariable='test567'}

从日志中可以看出bean在没有设置scope的时候,默认值为singletone的。另外即使属性类是protetype的时候,也会在父bean初始化将其填充。不会在调用父bean的时候,重新初始化属性所关联的bean。详细见例2

例2,在执行过程中,增加属性修改,咱们再来执行下看看

		//修改property bean实例中的变量simpleVariable
		simpleBean.getProperty().setSimpleVariable("aaaaa");
		//重新获取simpleBean实例
		simpleBean = context
				.getBean("simpleBean", SimpleBean.class);
		//再次执行test方法
		simpleBean.test();

看下新增的日志:

15:14:58.447 [main] INFO  c.l.spring.study.init.SimpleBean - SimpleBean is loading.SimpleBean{property=SimpleBeanProperty{simpleVariable='aaaaa'}}
15:14:58.447 [main] INFO  c.l.s.study.init.SimpleBeanProperty - propertyTest method is invoking.SimpleBeanProperty{simpleVariable='aaaaa'}

看来咱们之前的猜测是对的,

第一、bean的scope默认为SingleTone的

第二、bean的lazyInit为false的

第三、即使属性为prototype也不会再父bean为SingleTone的时重新初始化

例3、再增加两行

		//获取property实例
		SimpleBeanProperty property = context
				.getBean("property", SimpleBeanProperty.class);
		//测试propertyTest方法
		property.propertyTest();

再看下执行后新增的日志:

15:19:10.331 [main] DEBUG o.s.b.f.s.DefaultListableBeanFactory - Creating instance of bean 'property'
15:19:10.331 [main] INFO  c.l.s.study.init.SimpleBeanProperty - SimpleBeanProperty is loading.
15:19:10.331 [main] DEBUG o.s.b.f.s.DefaultListableBeanFactory - Finished creating instance of bean 'property'
15:19:10.331 [main] INFO  c.l.s.study.init.SimpleBeanProperty - propertyTest method is invoking.SimpleBeanProperty{simpleVariable='test567'}

由于property的bean由于是prototype的,所以被重新初始化了。

例4、再增加四行:

		//获取anotherBean实例
		SimpleAnotherBean anotherBean = context
				.getBean("anotherBean", SimpleAnotherBean.class);
		anotherBean.test();
		//设置变量的值
		anotherBean.setSimpleVariable("bbbbb");
		//重新获取anotherBean实例
		anotherBean = context
				.getBean("anotherBean", SimpleAnotherBean.class);
		anotherBean.test();

大家在看下执行日志:

15:23:13.130 [main] DEBUG o.s.b.f.s.DefaultListableBeanFactory - Creating instance of bean 'anotherBean'
15:23:13.130 [main] INFO  c.l.s.study.init.SimpleBeanProperty - SimpleAnotherBean is loading.
15:23:13.130 [main] DEBUG o.s.b.f.s.DefaultListableBeanFactory - Finished creating instance of bean 'anotherBean'
15:23:13.130 [main] INFO  c.l.s.study.init.SimpleBeanProperty - test method is invoking.SimpleAnotherBean{simpleVariable='test123'}
15:23:13.131 [main] DEBUG o.s.b.f.s.DefaultListableBeanFactory - Creating instance of bean 'anotherBean'
15:23:13.131 [main] INFO  c.l.s.study.init.SimpleBeanProperty - SimpleAnotherBean is loading.
15:23:13.131 [main] DEBUG o.s.b.f.s.DefaultListableBeanFactory - Finished creating instance of bean 'anotherBean'
15:23:13.131 [main] INFO  c.l.s.study.init.SimpleBeanProperty - test method is invoking.SimpleAnotherBean{simpleVariable='test123'}

bean为prototype的时候,每次都会被新初始化的

通过日志的内容,梳理一下大概初始化逻辑

可以看出主要针对beans context 还有core包。

具体怎么相互协作的,下一节会进一步介绍。

				
时间: 2024-11-09 00:29:29

spring framework 4 源码阅读(2)---从ClassPathXmlApplicationContext开始的相关文章

spring framework 4 源码阅读 --- 前期准备

在开始看代码之前,需要做的第一件事是下载代码. 在这里:https://github.com/spring-projects/spring-framework 下载完成了发现使用gradle做的源代码的构建管理工具的. 值得庆幸的事情,spring为导入eclipse写了脚本工具,包解压后结构如下: 发现了一个脚本文件:import-into-eclipse.bat,今天负责导入的就是他了, 等待漫长的编译,这里有个问题,在没有安装gradle的时候,脚本会自动下载gradle 执行完成后是这样

spring framework 4 源码阅读

前面写了几篇spring 的介绍文章,感觉与主题不是很切合.重新整理下思路,从更容易理解的角度来写下文章. spring 的骨架 spring 的骨架,也是spring 的核心包.主要包含三个内容 1.context:spring 的上线文-------导演 2.core:spring的核心包,主要包括spring所以用到的工具-------道具 3.beans:spring的bean实例 -------演员 导演负责安排演出,演员负责按照导演的指示来演出,演出过程中需要使用道具. 我想大家看完

spring framework项目源码github托管地址

方法一:直接下载,github托管地址:http://repo.spring.io/simple/libs-release-local/org/springframework/spring/ 方法二:svn检出 一次性源码全量包下载的方法.spring的项目包会托管到github网站上,所以可以从github网站上得到spring任意版本的全量包(使用svn客户端下载),方法如下:1.安装svn客户端,随便使用自己喜欢的一个就行,通常用的最多的是TortoiseSVN.自己下载安装.2.检出(下

Spring依赖注入源码阅读笔记

一.调用栈 一次典型的Spring依赖注入的调用栈: DefaultListableBeanFactory:getBean() AbstractBeanFactory:doGetBean() AbstractAutowireCapableBeanFactory:createBean() AbstractAutowireCapableBeanFactory:createBeanInstance() SimpleInstantiationStategy:instantiate() AbstractA

Spring源码阅读:Spring MVC 如何处理HTTP请求

Spring MVC 对HTTP请求的处理流程 通过之前的源码阅读,知道了ApplicationContext初始的过程,也知道了Spring MVC环境的初始化过程,今天就来了解一下SpringMVC是如何处理HTTP请求的. HTTP请求根据请求方式可以分为GET.POST.PUT.DELETE.OPTIONS.TRACE,最常用的还是GET和POST. Spring对于这几种HTTP请求的处理都是使用了processRequest(req,rep); @Override protected

Spring源码阅读:IOC容器的设计与实现(二)——ApplicationContext

上一主题中,了解了IOC容器的基本概念,以及BeanFactory的设计与实现方式,这里就来了解一下ApplicationContext方式的实现. ApplicationContext 在Spring的参考文档中,为啥要推荐使用ApplicationContext?它能给我们的应用带来什么好处呢?作为BeanFactory的实现之一,它又是如何设计的?在SpringMVC中使用的WebApplictionContext\XmlApplicationContext与之有何关联? Applicat

Spring源码阅读:Spring声明式事务处理和编程式事务处理的设计与实现

之前的学习,了解了Spring事务管理的基础框架(查看).Spring在此基础上又提到了声明式事务管理和编程式事务管理.这里就来看看Spring是如何实现的. Spring声明式事务与EJB事务管理对比 Spring的声明式管理,类似于EJB的CMT,但又有不同.他们的不同之处有: 1)EJB的CMT是与JTA结合使用,而Spring框架的声明式事务管理可以在任何环境下工作.既可以使用全局事务管理,如JTA,也可以使用局部事务管理如JDBCJPA.Hibernate.JDO等. 2)可以在任何类

Spring源码阅读:Spring如何支持各种ORM框架

为了让开发程序更容易,到现在为止,已经有很多ORM框架了,例如:JPA,JDO,Hibernate,Mybatis(之前版本是IBatis)等等.也正因为已经有这么多优秀的ORM框架,Spring团队并没有自己开发一套ORM框架,而是对这些框架都进行了支持,让这些框架在Spring环境下可以得到完全的应用. 通常,在Spring环境下使用这些ORM框架时,都会通过一个Template来使用.Spring对这些框架的集成是这样的: 例如Hibernate,在使用Hibernate时(没有在Spri

Spring源码阅读:Spring事务管理的基础

上一节了解了全局事务与局部事务以及Spring提供的两种事务模式:编程式事务与声明式事务. 不论是编程式的事务处理,还是声明式的事务处理.他们都要对局部事务和全局事务以支持,也就是说要对JDBC进行支持.ORM框架,同时也要对JTA进行支持.他们的公共部分是commit,rollback.通过这一节的了解,我相信以后配置Spring事务时,就不需要在去网上查资料了或者去查Spring的参考文档了. 因此,Spring设计了如下的事务管理框架: 从上面的类图中和容易可以看出分为三部分:Platfo