spring在 web项目里启动原理分析

IoC(核心中的核心):Inverse of Control,控制反转。对象的创建权力由程序反转给Spring框架。

AOP:Aspect Oriented Programming,面向切面编程。在不修改目标对象的源代码情况下,增强IoC容器中Bean的功能。

DI:Dependency Injection,依赖注入。在Spring框架负责创建Bean对象时,动态的将依赖对象注入到Bean组件中!!

Spring容器:指的就是IoC容器。

 

 

1    Spring IoC原理分析

***要想使用Spring IoC,必须要创建Spring IoC容器。

       ***那么什么是IoC容器呢?

       ***如何创建IoC容器呢?

       ***IoC容器是如何初始化Bean实例的呢?

1.1       什么是IoC容器?

什么是IoC容器?

***所谓的IoC容器就是指的Spring中Bean工厂里面的Map存储结构(存储了Bean的实例)。

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 容器。它用来读取注解。

Java应用中创建IoC容器:(了解)

ApplicationContext context = new ClassPathXmlApplicationContext(xml路径);

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》

  1. web服务器(tomcat)启动会加载web.xml(启动ContextLoaderListener监听器):

 

 

 

  1. 创建Web环境中的Spring容器

 

 

 

  1. ContextLoader类中创建Spring容器并初始化容器中的Bean实例

 

 

 

  1. 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();

                     }

              }

       }

posted @ 2020-05-10 18:49  会游泳的小猪  阅读(416)  评论(0)    收藏  举报