启动流程
- Tomcat运行时会去读取web.xml文件,web.xml文件中引用了Spring,SpringMVC核心两大类(ContextLoaderListener,DispatcherServlet)
- 初始化上下文(ContextLoaderListener的contextInitialized—>ContextLoader.initWebApplicationContext)
- 创建ApplicationContext
- 创建ConfigurableWebApplicationContext,ApplicationContext属性setter.
- 实例化ApplicationContext属性
- BeanFactory IOC容器构建
- Bean载入
//ContextLoader
/**
* 初始化上下文
* */
public WebApplicationContext initWebApplicationContext(ServletContext servletContext) {
.......
//创建ApplicationContext引用
this.context = this.createWebApplicationContext(servletContext);
if (this.context instanceof ConfigurableWebApplicationContext) {
ConfigurableWebApplicationContext cwac = (ConfigurableWebApplicationContext)this.context;
if (!cwac.isActive()) {
if (cwac.getParent() == null) {
ApplicationContext parent = this.loadParentContext(servletContext);
cwac.setParent(parent);
}
//初始化ApplicationContext、国际化,Bean加载。(此刻就进入了SpringBean初始化流程)
this.configureAndRefreshWebApplicationContext(cwac, servletContext);
}
}
servletContext.setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, this.context);
ClassLoader ccl = Thread.currentThread().getContextClassLoader();
if (ccl == ContextLoader.class.getClassLoader()) {
currentContext = this.context;
} else if (ccl != null) {
currentContextPerThread.put(ccl, this.context);
}
......
return this.context;
......
}
/***
* 初始化ApplicationContext
* */
protected void configureAndRefreshWebApplicationContext(ConfigurableWebApplicationContext wac, ServletContext sc) {
String configLocationParam;
configLocationParam = sc.getInitParameter("contextId");
wac.setId(configLocationParam);
wac.setId(ConfigurableWebApplicationContext.APPLICATION_CONTEXT_ID_PREFIX + ObjectUtils.getDisplayString(sc.getContextPath()));
//上下文切换,可以说是ConfigurableWebApplicationContext对ServletContext进行属性添加。
//不在ServletContext添加代码
wac.setServletContext(sc);
//此处获取到xml中的contextConfigLocation配置对象,
configLocationParam = sc.getInitParameter("contextConfigLocation");
if (configLocationParam != null) {
wac.setConfigLocation(configLocationParam);
}
ConfigurableEnvironment env = wac.getEnvironment();
if (env instanceof ConfigurableWebEnvironment) {
((ConfigurableWebEnvironment)env).initPropertySources(sc, (ServletConfig)null);
}
this.customizeContext(sc, wac);
//Spring bean 初始化
wac.refresh(); // ---->ConfigurableApplicationContext.refresh ---->AbstractApplicationContext.refresh
}
//AbstractApplicationContext
public void refresh() throws BeansException, IllegalStateException {
.....
//BeanDefinition(IOC容器创建,Springbean加载)
ConfigurableListableBeanFactory beanFactory = this.obtainFreshBeanFactory();
//允许在上下文的子类中对bean factory进行后处理
this.postProcessBeanFactory(beanFactory);
//调用bean factory 后置方法
this.invokeBeanFactoryPostProcessors(beanFactory);
//注册BeanPostProcessor
this.registerBeanPostProcessors(beanFactory);
//初始国际化文件 i18n
this.initMessageSource();
// 初始化事件监听多路广播器
this.initApplicationEventMulticaster();
// 模板方法而已,可以根据不同的spring容器做不同的事情
//比如web程序的容器ServletWebServerApplicationContext中会调用createWebServer方法去创建内置的Servlet容器。
this.onRefresh();
//注册监听器
this.registerListeners();
//初始化所有的单例bean
this.finishBeanFactoryInitialization(beanFactory);
//刷新完成工作
this.finishRefresh();
....
/**
* bean工厂初始化
* */
protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {
.......
beanFactory.setTempClassLoader((ClassLoader)null);
beanFactory.freezeConfiguration();
//预实例化所有非懒加载单例Bean 传说中的spring bean 循环依赖问题,spring bean加载
//就是在此处。下方有专门介绍
beanFactory.preInstantiateSingletons();
//---->ConfigurableListableBeanFactory.preInstantiateSingletons
//---->DefaultListableBeanFactory.preInstantiateSingletons
}
protected final void refreshBeanFactory() throws BeansException {
//如果已经有了Bean工厂,直接摧毁重建
if (this.hasBeanFactory()) {
this.destroyBeans();
this.closeBeanFactory();
}
try {
//DefauliListableBeanFactory 就是IOC容器
DefaultListableBeanFactory beanFactory = this.createBeanFactory();
beanFactory.setSerializationId(this.getId());
this.customizeBeanFactory(beanFactory);
//用IOC容器构建Bean。Bean的初始化流程就在这里,核心之核弹级重点。
//该方法有支持XML读取,注解形式读取Bean。核心就是根据path遍历读取Bean对象,
this.loadBeanDefinitions(beanFactory);
synchronized(this.beanFactoryMonitor) {
this.beanFactory = beanFactory;
}
} catch (IOException var5) {
throw new ApplicationContextException("I/O error parsing bean definition source for " + this.getDisplayName(), var5);
}
}
//DefaultListableBeanFactory
public void preInstantiateSingletons() throws BeansException {
while(true) {
while(true) {
String beanName;
RootBeanDefinition bd;
do {
do {
do {
.......
}
beanName = (String)var2.next();
bd = this.getMergedLocalBeanDefinition(beanName);
} while(bd.isAbstract()); //是否是抽象
} while(!bd.isSingleton()); //是否是单例模式
} while(bd.isLazyInit()); //是否是懒加载
//如果同时满足以上条件,则会进行实例化操作
if (this.isFactoryBean(beanName)) {
//判断bean是否实现了 FactoryBean接口,实现了进行一 次&前缀初始化,一次本类实例化 isFactoryBean(beanName)
//大多数普通类直接调用 getBean(beanName);
final FactoryBean<?> factory = (FactoryBean)this.getBean("&" + beanName);
boolean isEagerInit;
if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) {
isEagerInit = (Boolean)AccessController.doPrivileged(new PrivilegedAction<Boolean>() {
public Boolean run() {
return ((SmartFactoryBean)factory).isEagerInit();
}
}, this.getAccessControlContext());
} else {
isEagerInit = factory instanceof SmartFactoryBean && ((SmartFactoryBean)factory).isEagerInit();
}
if (isEagerInit) {
this.getBean(beanName);
}
} else {
this.getBean(beanName); //--->AbstractBeanFactory.getBean.doGetBean
}
}
}
}
//AbstractBeanFactory
protected <T> T doGetBean(String name, @Nullable Class<T> requiredType, @Nullable Object[] args, boolean typeCheckOnly) throws BeansException {
String beanName = this.transformedBeanName(name);
//尝试性从缓存中获取bean对象
Object sharedInstance = this.getSingleton(beanName);
Object bean;
if (sharedInstance != null && args == null) {
if (this.logger.isTraceEnabled()) {
if (this.isSingletonCurrentlyInCreation(beanName)) {
this.logger.trace("Returning eagerly cached instance of singleton bean '" + beanName + "' that is not fully initialized yet - a consequence of a circular reference");
} else {
this.logger.trace("Returning cached instance of singleton bean '" + beanName + "'");
}
}
bean = this.getObjectForBeanInstance(sharedInstance, name, beanName, (RootBeanDefinition)null);
} else {
//查看当前的bean是否在创建中并且是prototype作用域
// 如果是创建中,此处又引用到了bean,着是判定为循环引用
if (this.isPrototypeCurrentlyInCreation(beanName)) {
throw new BeanCurrentlyInCreationException(beanName);
}
........
//这里也比较重要,这里涉及到当前创建的bean是什么作用域的
//单例模式
if (mbd.isSingleton()) {
//创建bean。能走到这里来,就说明当前操作的bean没有在三级缓存之中!
//原型模式
} else if (mbd.isPrototype()) {
} else {
//如果既不是单例Bean,也不是原型,则获取其Scope
String scopeName = mbd.getScope();
}
}
三级缓存源码
DefaultSingletonBeanRegistry
/**
* 此方法只是尝试性的从缓存获取。
* */
@Nullable
protected Object getSingleton(String beanName, boolean allowEarlyReference) {
/** 从一级缓存找,是否有实例化好的Bean对象 **/
Object singletonObject = this.singletonObjects.get(beanName);
/** 如果一级缓存找不到**/
if (singletonObject == null && this.isSingletonCurrentlyInCreation(beanName)) {
/** 从二级缓存找,是否有提前曝光的Bean对象引用 **/
singletonObject = this.earlySingletonObjects.get(beanName);
if (singletonObject == null && allowEarlyReference) {
synchronized(this.singletonObjects) {
singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null) {
singletonObject = this.earlySingletonObjects.get(beanName);
if (singletonObject == null) {
/** 从三级缓存找,找到Bean对象的工厂。然后进行构建对象,存放到二级缓存。在删掉三级缓存 **/
ObjectFactory<?> singletonFactory = (ObjectFactory)this.singletonFactories.get(beanName);
if (singletonFactory != null) {
singletonObject = singletonFactory.getObject();
this.earlySingletonObjects.put(beanName, singletonObject);
this.singletonFactories.remove(beanName);
}
}
}
}
}
}
return singletonObject;
}
/**
* 如果在缓存中获取不到,则会调用该方法,进行创建bean
* */
public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {
.....
synchronized(this.singletonObjects) {
......
//便于对循环依赖进行检测的,可能由于创建的时候没有暴露出来对象
this.beforeSingletonCreation(beanName);
......
try {
//创建单例bean对象.Bean的生命周期以及依赖注入添加到三级缓存的真正入口。非常庞大设计
// 下面单独写出
singletonObject = singletonFactory.getObject();
.......
//
this.afterSingletonCreation(beanName);
}
......
}
return singletonObject;
}
}
五种作用域
-
singleton:单例模式,当spring创建applicationContext容器的时候,spring会欲初始化所有的该作用域实例,加上lazy-init就可以避免预处理;
-
prototype:原型模式,每次通过getBean获取该bean就会新产生一个实例,创建后spring将不再对其管理;
-
request:搞web的大家都应该明白request的域了吧,就是每次请求都新产生一个实例,和prototype不同就是创建后,接下来的管理,spring依然在监听
-
session:每次会话,同上
-
global session:全局的web域,类似于servlet中的application
Spring 默认的Bean是为单例模式。在spring开发中,本身就是线程不安全的,但线程执行的方法隔绝了数据共享。如果在全局引用变量,则会引发并发问题。
BeanFactory 与 FactoryBean
- BeanFactory是Spring IOC 容器接口基本定义。
- FactoryBean是Spring 对 Bean创建自定义处理的类。本身就是一个工厂和装饰。主要还是为了解决XML bean配置的繁琐问题。
Spring中运用到的设计模式
- BeanFactory工厂模式
- Spring启动时,加载Class文件转换成Bean元素,Bean元素在转换成BeanDefinition对象。通过不同的BeanName能获取到Ioc不同的实例对象。经典的工厂模式
- getSingleton单列模式
- Spring在获取Bean的时候,会去三级缓存中寻找Bean。并且加了双重锁,双重判断的单例模式
- SpringMVC中的HandlerAdatper 适配器
- AOP代理模式
- 动态代理在内存中构建,不需要额外的去创建代理类
- 模板设计
- 在Spring中,很多父类定义了抽象方法,子类在集成中都用得到,并且可以通过模板设计控制父类的方法元素。
- Map也有这个设计,Map定义了模板方法,HashMap进行了实现,LinkedHashMap 实现HashMap,用钩子方法控制HashMap的属性