一、 Spring 运行原理
- Spring 启动时读取应用程序提供的 Bean 配置信息,
- 并在 Spring 容器中生成一份相应的Bean 配置注册表;
- 然后根据这张注册表实例化 Bean,装配好 Bean 之间的依赖关系,
- 将Bean放回bean缓冲池等待上层应用调用;
- 应用程序需要使用bean时从Bean缓冲池中获取
- 为上层应用提供准备就绪的运行环境。
二、 Spring 源码分析
1 ApplicationContext
1.1Spring 中 IOC 容器分类
Spring 中有两个主要的容器系列:
1)实现 BeanFactory 接口的简单容器; 只提供了对对象生命周期的管理
2)实现 ApplicationContext 接口的高级容器。 不仅包含了BeanFactory的能力,而且提供了额外的能力。
1.2ApplicationContext 容器介绍
ApplicationContext内部封装了一个BeanFactory对象,来实现对容器的操作,BeanFactory 封装了 bean 的信息,而 ApplicationContext 通过访问 BeanFactory 对象获取 bean 的对象信息 。
ApplicationContext 也 实 现 了 一 系 列 的 BeanFactory 接 口 ( 可 以 说 ApplicationContext 对 BeanFactory 对象实现一种代理)。ApplicationContext 在应用这个 DefaultListableBeanFactory 对象的基础上,不仅实现了BeanFactory 接口提供的功能方法,并且黏合了一些面向应用的功能,如资源/国际化支持/ 框架事件支持等 。
public interface ApplicationContext extends EnvironmentCapable,
ListableBeanFactory, //继承于 BeanFactory
HierarchicalBeanFactory,//继承于 BeanFactory
MessageSource, //
ApplicationEventPublisher,//
ResourcePatternResolver //继承 ResourceLoader,用于获取 resource 对象 配置文件
可以看出最终ClassPathXmlApplicationContext 实现了这个接口,就下来就分析ApplicationContext 的启动流程。
2 ClassPathXmlApplicationContext
调用了ClassPathXmlApplicationContext(String configLocation)构造方法;
ClassPathXmlApplicationContext(String configLocation)方法又调用了另一个构造方法:
2.1refresh()方法
这个构造方法中有一个重要的方法:refresh()方法 是整个Spring IoC容器初始化的入口方法。
下面是refresh()方法中的介绍:
红色标记为重要。
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
// Prepare this context for refreshing.
prepareRefresh();
// Tell the subclass to refresh the internal 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) {
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;
}
}
}
obtainFreshBeanFactory()方法创建Bean工厂,然后才能实现对BeanDefinition的装配。
接下来查看obtainFreshBeanFactory()源码:
其中首先执行refreshBeanFactory()方法:查看源码,这里是AbstractRefreshableApplicationContext
这里调用了一个重要的方法createBeanFactory创建了DefaultListableBeanFactory对象;
2.2实例化 Bean 工厂
2.2.1DefaultListableBeanFactory
在 BeanFactory 子类中有一个 DefaultListableBeanFactory 类,它包含了基本 Spirng IoC 容器所具有的重要功能,开发时不论是使用 BeanFactory 系列还是 ApplicationContext 系列来创建容器基本都会使用到 DefaultListableBeanFactory 类,可以这么说,在 spring 中实际上把 它当成默认的 IoC 容器来使用。
这里的beanFactory最终还是DefaultListableBeanFactory。
DefaultListableBeanFactory中Map用于解析配置文件后填充,(就是图中的注册表)用于BeanFactory对Bean的实例化。
private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<String, BeanDefinition>(64);
接下来分析解析配置文件的代码
2.3解析配置文件
loadBeanDefinitions方法用于加载Bean,传入DefaultListableBeanFactory
2.3.1XmlBeanDefinitionReader
帮助完成xml解析,吧把Bean的信息放到注册表中,
- 首先初始化beanDefinitionReader,
- 然后读取初始化完成后的bean,
- 最后将对象传入loadBeanDefinitions方法中。
这里走容器自身资源,遍历配置文件,每循环一次,就使用loadBeanDefinitions(String location)解析一次,
loadBeanDefinitions(String location)中调用构造方法:
然后又调用构造方法:
遍历resource,调用XmlBeanDefinitionreader中的loadBeanDefinitions方法;
接着调
调:
public int loadBeanDefinitions(EncodedResource encodedResource) throws BeanDefinitionStoreException {
Assert.notNull(encodedResource, "EncodedResource must not be null");
//初始化
if (logger.isInfoEnabled()) {
logger.info("Loading XML bean definitions from " + encodedResource.getResource());
}
Set<EncodedResource> currentResources = this.resourcesCurrentlyBeingLoaded.get();
if (currentResources == null) {
currentResources = new HashSet<EncodedResource>(4);
this.resourcesCurrentlyBeingLoaded.set(currentResources);
}
if (!currentResources.add(encodedResource)) {
throw new BeanDefinitionStoreException(
"Detected cyclic loading of " + encodedResource + " - check your import definitions!");
}
try {
InputStream inputStream = encodedResource.getResource().getInputStream();//获取配置文件信息
try {
InputSource inputSource = new InputSource(inputStream);//spring解析xml使用sax方式,需要InputSource转化类型
if (encodedResource.getEncoding() != null) {
inputSource.setEncoding(encodedResource.getEncoding());
}
return doLoadBeanDefinitions(inputSource, encodedResource.getResource());//调用解析
}
finally {
inputStream.close();
}
}
catch (IOException ex) {
throw new BeanDefinitionStoreException(
"IOException parsing XML document from " + encodedResource.getResource(), ex);
}
finally {
currentResources.remove(encodedResource);
if (currentResources.isEmpty()) {
this.resourcesCurrentlyBeingLoaded.remove();
}
}
}
传入document 和创建读取xml文件的上下文对象
循环遍历root节点
解析完配置文件后就该注册Bean了
3 将 BeanDefiniton 注册到容器中
processBeanDefinition方法:
每次根据解析出来的Bean标签都会创建,返回的BeanDefinitionHolder对象,这个对象是对解析出来结果的定义,并且能完成将解析出的结果注册到Spring Ioc容器中。每次根据解析出来的Bean标签都会创建。
使用了工具类BeanDefinitionReaderUtils中的registerBeanDefinition方法完成注册。
registerBeanDefinition:首先取出beanName,然后调用registerBeanDefinition
调用:
public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)
throws BeanDefinitionStoreException {
Assert.hasText(beanName, "Bean name must not be empty");
Assert.notNull(beanDefinition, "BeanDefinition must not be null");
if (beanDefinition instanceof AbstractBeanDefinition) {
try {
((AbstractBeanDefinition) beanDefinition).validate();
}
catch (BeanDefinitionValidationException ex) {
throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName,
"Validation of bean definition failed", ex);
}
}
BeanDefinition oldBeanDefinition;
oldBeanDefinition = this.beanDefinitionMap.get(beanName);
if (oldBeanDefinition != null) {
if (!this.allowBeanDefinitionOverriding) {
throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName,
"Cannot register bean definition [" + beanDefinition + "] for bean '" + beanName +
"': There is already [" + oldBeanDefinition + "] bound.");
}
else if (oldBeanDefinition.getRole() < beanDefinition.getRole()) {
// e.g. was ROLE_APPLICATION, now overriding with ROLE_SUPPORT or ROLE_INFRASTRUCTURE
if (this.logger.isWarnEnabled()) {
this.logger.warn("Overriding user-defined bean definition for bean '" + beanName +
" with a framework-generated bean definition ': replacing [" +
oldBeanDefinition + "] with [" + beanDefinition + "]");
}
}
else {
if (this.logger.isInfoEnabled()) {
this.logger.info("Overriding bean definition for bean '" + beanName +
"': replacing [" + oldBeanDefinition + "] with [" + beanDefinition + "]");
}
}
}
else {
this.beanDefinitionNames.add(beanName);
this.manualSingletonNames.remove(beanName);
this.frozenBeanDefinitionNames = null;
}
//将解析出来的配置文件通过key:beanName value:beanDefinition(bean的信息)的形式放入map(注册表中)
this.beanDefinitionMap.put(beanName, beanDefinition);
if (oldBeanDefinition != null || containsSingleton(beanName)) {
resetBeanDefinition(beanName);
}
}
完成祖册后,接下来就是实例化Bean
4 Bean 对象的实例化
refresh()中的 finishBeanFactoryInitialization(beanFactory);
实例化单例模式(不是懒加载)的bean
public void preInstantiateSingletons() throws BeansException {
if (this.logger.isDebugEnabled()) {
this.logger.debug("Pre-instantiating singletons in " + this);
}
// Iterate over a copy to allow for init methods which in turn register new bean definitions.
// While this may not be part of the regular factory bootstrap, it does otherwise work fine.
List<String> beanNames = new ArrayList<String>(this.beanDefinitionNames);//获得beanNames信息
// Trigger initialization of all non-lazy singleton beans...
for (String beanName : beanNames) {
RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);//获得bean信息
if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {//判断是否被实例化
if (isFactoryBean(beanName)) {
//如果没有被实例化,调用getBean方法拿beanName拼上前缀获得相应的FactoyBean
final FactoryBean<?> factory = (FactoryBean<?>) getBean(FACTORY_BEAN_PREFIX + beanName);
boolean isEagerInit;
if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) {
isEagerInit = AccessController.doPrivileged(new PrivilegedAction<Boolean>() {
@Override
public Boolean run() {
return ((SmartFactoryBean<?>) factory).isEagerInit();//实例化Bean
}
}, getAccessControlContext());
}
else {
isEagerInit = (factory instanceof SmartFactoryBean &&
((SmartFactoryBean<?>) factory).isEagerInit());
}
if (isEagerInit) {
getBean(beanName);
}
}
else {
getBean(beanName);
}
}
}
// Trigger post-initialization callback for all applicable beans...
for (String beanName : beanNames) {
Object singletonInstance = getSingleton(beanName);
if (singletonInstance instanceof SmartInitializingSingleton) {
final SmartInitializingSingleton smartSingleton = (SmartInitializingSingleton) singletonInstance;
if (System.getSecurityManager() != null) {
AccessController.doPrivileged(new PrivilegedAction<Object>() {
@Override
public Object run() {
smartSingleton.afterSingletonsInstantiated();
return null;
}
}, getAccessControlContext());
}
else {
smartSingleton.afterSingletonsInstantiated();
}
}
}
}
5 GetBean
getBeanFactory()还是之前的那个,返回DefaultListableBeanFactory.
DefaultListableBeanFactory下的getBean方法:传入接口的类型
调用的:
public <T> T getBean(Class<T> requiredType, Object... args) throws BeansException {
Assert.notNull(requiredType, "Required type must not be null");
//userServiceImpl如果spring中不是通过xml配置的,而是通过注解(key:类名首字母小写value:beanDefinition)
//beanName就是爱spring ioc容器中缓存的bean对象的唯一标记,根据标记取得对象
String[] beanNames = getBeanNamesForType(requiredType);
if (beanNames.length > 1) {
ArrayList<String> autowireCandidates = new ArrayList<String>();
for (String beanName : beanNames) {
if (!containsBeanDefinition(beanName) || getBeanDefinition(beanName).isAutowireCandidate()) {
autowireCandidates.add(beanName);
}
}
if (autowireCandidates.size() > 0) {
beanNames = autowireCandidates.toArray(new String[autowireCandidates.size()]);
}
}
if (beanNames.length == 1) {
return getBean(beanNames[0], requiredType, args);//
}
else if (beanNames.length > 1) {
Map<String, Object> candidates = new HashMap<String, Object>();
for (String beanName : beanNames) {
candidates.put(beanName, getBean(beanName, requiredType, args));
}
String primaryCandidate = determinePrimaryCandidate(candidates, requiredType);
if (primaryCandidate != null) {
return getBean(primaryCandidate, requiredType, args);
}
String priorityCandidate = determineHighestPriorityCandidate(candidates, requiredType);
if (priorityCandidate != null) {
return getBean(priorityCandidate, requiredType, args);
}
throw new NoUniqueBeanDefinitionException(requiredType, candidates.keySet());
}
else if (getParentBeanFactory() != null) {
return getParentBeanFactory().getBean(requiredType, args);
}
else {
throw new NoSuchBeanDefinitionException(requiredType);
}
}
getBean:
doGetBean:
protected <T> T doGetBean(
final String name, final Class<T> requiredType, final Object[] args, boolean typeCheckOnly)
throws BeansException {
final String beanName = transformedBeanName(name);
Object bean;
// Eagerly check singleton cache for manually registered singletons.
Object sharedInstance = getSingleton(beanName);
if (sharedInstance != null && args == null) {
if (logger.isDebugEnabled()) {
if (isSingletonCurrentlyInCreation(beanName)) {
logger.debug("Returning eagerly cached instance of singleton bean '" + beanName +
"' that is not fully initialized yet - a consequence of a circular reference");
}
else {
logger.debug("Returning cached instance of singleton bean '" + beanName + "'");
}
}
bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
}
...
}
先通过给定的接口类型转化得出接口实现类的名称,然后拿着这个名称作为取key的标记,用标记获得beanDefinition