spring在 web项目里启动原理分析
l IoC(核心中的核心):Inverse of Control,控制反转。对象的创建权力由程序反转给Spring框架。
l AOP:Aspect Oriented Programming,面向切面编程。在不修改目标对象的源代码情况下,增强IoC容器中Bean的功能。
l DI:Dependency Injection,依赖注入。在Spring框架负责创建Bean对象时,动态的将依赖对象注入到Bean组件中!!
l Spring容器:指的就是IoC容器。
1 Spring IoC原理分析
***要想使用Spring IoC,必须要创建Spring IoC容器。
***那么什么是IoC容器呢?
***如何创建IoC容器呢?
***IoC容器是如何初始化Bean实例的呢?
1.1 什么是IoC容器?
l 什么是IoC容器?
***所谓的IoC容器就是指的Spring中Bean工厂里面的Map存储结构(存储了Bean的实例)。
l Spring框架中的工厂有哪些?
***ApplicationContext接口()
* 实现了BeanFactory接口
* 实现ApplicationContext接口的工厂,可以获取到容器中具体的Bean对象
***BeanFactory工厂(是Spring框架早期的创建Bean对象的工厂接口)
* 实现BeanFactory接口的工厂也可以获取到Bean对象
***其实通过源码分析,不管是BeanFactory还是ApplicationContext,其实最终的底层BeanFactory都是DefaultListableBeanFactory
l ApplicationContext和BeanFactory的区别?
***创建Bean对象的时机不同:
***BeanFactory采取延迟加载,第一次getBean时才会初始化Bean。
***ApplicationContext是加载完applicationContext.xml时,就创建具体的Bean对象的实例。(只对BeanDefition中描述为是单例的bean,才进行饿汉式加载)
1.2 如何创建Web环境中的IoC容器?
1.2.1 创建方式
l ApplicationContext接口常用实现类
***ClassPathXmlApplicationContext:
它是从类的根路径下加载配置文件 推荐使用这种
***FileSystemXmlApplicationContext:
它是从磁盘路径上加载配置文件,配置文件可以在磁盘的任意位置。
***AnnotationConfigApplicationContext:
当我们使用注解配置容器对象时,需要使用此类来创建 spring 容器。它用来读取注解。
l Java应用中创建IoC容器:(了解)
ApplicationContext context = new ClassPathXmlApplicationContext(xml路径);
l Web应用中创建IoC容器:(重点)
web.xml中配置ContextLoaderListener接口,并配置ContextConfigLocation参数
***web容器启动之后加载web.xml,此时加载ContextLoaderListener监听器(实现了ServletContextListener接口,该接口的描述请见下面《三类八种监听器》)
***ContextLoaderListener监听器会在web容器启动的时候,触发contextInitialized()方法。
***contextInitialized()方法会调用initWebApplicationContext()方法,该方法负责创建Spring容器(DefaultListableBeanFactory)。
【Web三类八种监听器】: ***监听域对象的生命周期: *ServletContextListener: *创建:服务器启动 *销毁:服务器正常关闭 *spring ContextLoaderListener(服务器启动时负责加载Spring配置文件) *HttpSessionListener *创建:第一次访问request.getHttpSession(); *销毁:调用invalidate();非法关闭;过期 *ServletRequestListener *创建:每一次访问 *销毁:响应结束 ***监听域对象的属性:(添加、删除、替换) * ServletContextAttributeListener * HttpSessionAttributeListener * ServletRequestAttributeListener ***监听HttpSession中JavaBean的改变: * HttpSessionBindingListener(HttpSession和JavaBean对象的绑定和解绑) * HttpSessionActivationListener(HttpSession的序列化,活化、钝化)
|
1.2.2 源码分析
参考资料中的源码工程《spring-sourcecode》
- web服务器(tomcat)启动会加载web.xml(启动ContextLoaderListener监听器):
- 创建Web环境中的Spring容器
- ContextLoader类中创建Spring容器并初始化容器中的Bean实例
- configureAndRefreshWebApplicationContext方法中调用最终初始化Bean的refresh方法
1.2.3 图示
该图示主要是分析上面第三步中【创建Spring容器】的图示
1.3 IoC容器如何创建Bean对象?
1.3.1 源码分析
源码来源于AbstractApplicationContext类:
@Override public void refresh() throws BeansException, IllegalStateException { synchronized (this.startupShutdownMonitor) { // Prepare this context for refreshing. prepareRefresh();
//1.创建真正的Spring容器(DefaultListableBeanFactory) //2.加载BeanDefition(描述要初始化的Bean的信息) //3.将BeanDefition注册到BeanDefitionRegistry // 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);
//执行实现了BeanFactoryPostProcessor接口的Bean //比如PropertyPlaceHolderConfigurer(context:property-placeholer)就是此处被调用的,替换掉BeanDefition中的占位符(${})中的内容 // Invoke factory processors registered as beans in the context. invokeBeanFactoryPostProcessors(beanFactory);
//注册BeanPostProcessor(后置处理器) //比如容器自动装载了一个AutowiredAnnotationBeanPostProcessor后置处理器(实现@Autowired注解功能) // 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();
//初始化非懒加载方式的单例Bean实例 // Instantiate all remaining (non-lazy-init) singletons. finishBeanFactoryInitialization(beanFactory);
// Last step: publish corresponding event. finishRefresh(); }
catch (BeansException ex) { if (logger.isWarnEnabled()) { 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; }
finally { // Reset common introspection caches in Spring's core, since we // might not ever need metadata for singleton beans anymore... resetCommonCaches(); } } } |