`
winworm
  • 浏览: 4284 次
  • 性别: Icon_minigender_1
  • 来自: 北京
文章分类
社区版块
存档分类
最新评论

Spring bean上下文环境在web环境的初始化概述

阅读更多
 
 
spring web服务在tomcat容器中启动的流程
 
 
在介绍spring启动流程之前,先介绍2个概念 servlet ServletContext
servlet java web服务的核心组件,可以简单理解为servlet是能接收并处理web请求的服务(典型的就是http请求)
ServletContext 是生成并维护servlet的上下文,存在于特定容器之中,如tomcatjettyresin等等
 
容器启动过程中解析web.xml 文件,它描述了一个web服务的关键信息,一般情况下包括servlet filterlistener
 
容器启动时将通知相关的listener,一般情况下spring环境就是这个时候引入的。
执行相关Servlet(如果设置为容器启动时执行)
filter初始化并执行init方法
filterservlet接收请求过程中之前都会执行
 
 
下面介绍spring 是如何在web环境中被初始化的
 
StandardContext.listenerStart() 启动web.xml 中配置的监听器(这个监听器在容器初始化时执行)
这里的StandardContext就是tomcat容器中的servlet环境
 
 
 
 
 
 
 
 
 
 
 
从上面可以看出,启动过程为,tomcat容器读取web.xml 初始化servlet容器StandardContext,配置listenerfilterservlet,初始化成功后触发相应的监听器,servlet(如果设置为load-on-startup
 
 
 
现在看集成springweb项目一般的web.xml示例:
 
<?xmlversion="1.0"encoding="UTF-8"?>
<web-appxmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://java.sun.com/xml/ns/javaee"xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
version="3.0">
<context-param>
<param-name>webAppRootKey</param-name>
<param-value>zhixiao.root</param-value>
</context-param>
<!-- session timeout, minutes unit -->
<session-config>
<session-timeout>10</session-timeout>
</session-config>
<!-- default home page -->
<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
<display-name>parking Created Web Application</display-name>
<!-- sprint/* -->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/spring/*.xml</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.util.Log4jConfigListener</listener-class>
</listener>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<listener> <!-- 可以去掉,因为spring mvc DispatchServlet 支持request session 作用范围的bean -->
<listener-class>org.springframework.web.context.request.RequestContextListener</listener-class>
</listener>
<!-- Spring 刷新Introspector防止内存泄露 -->
<listener>
<listener-class>org.springframework.web.util.IntrospectorCleanupListener</listener-class>
</listener>
<!-- encoding -->
<filter>
<filter-name>encodingFilter</filter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>UTF-8</param-value>
</init-param>
<init-param>
<param-name>forceEncoding</param-name>
<param-value>true</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>encodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<!-- redis session接管 -->
<filter>
<display-name>RedisSessionFilter</display-name>
<filter-name>RedisSessionFilter</filter-name>
<filter-class>com.qhyu.zhixiao.session.RedisSessionFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>RedisSessionFilter</filter-name>
<url-pattern>/*</url-pattern>
<dispatcher>REQUEST</dispatcher>
<dispatcher>FORWARD</dispatcher>
</filter-mapping>
<!-- ip checking -->
<filter>
<filter-name>ipFilter</filter-name>
<filter-class>com.qhyu.zhixiao.filter.IpFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>ipFilter</filter-name>
<url-pattern>/*</url-pattern>
<dispatcher>REQUEST</dispatcher>
<dispatcher>FORWARD</dispatcher>
</filter-mapping>
 
<!-- springmvc -->
<servlet>
<servlet-name>springmvc</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>springmvc</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>default</servlet-name>
<url-pattern>*.css</url-pattern>
</servlet-mapping>
</web-app>
 
 
 
下面重点看 ContextLoaderListener
 
这个listenertomcat容器启动时执行
 
publicclass ContextLoaderListener extends ContextLoader implements ServletContextListener {
public ContextLoaderListener() {}
public ContextLoaderListener(WebApplicationContext context) {
super(context);
}
/**
* Initialize the root web application context.
*/
@Override
publicvoid contextInitialized(ServletContextEvent event) {
initWebApplicationContext(event.getServletContext());
}
@Override
publicvoid contextDestroyed(ServletContextEvent event) {
closeWebApplicationContext(event.getServletContext());
ContextCleanupListener.cleanupAttributes(event.getServletContext());
}
}
 
initWebApplicationContext 方法就是初始化spring的入口,参数就是tomcat容器初始化的servlet
 
 
进入
initWebApplicationContext方法主要干了两件事
1.初始化WebApplicationContext
WebApplicationContext context = null;
if (this.context == null) {
this.context = createWebApplicationContext(servletContext);
}
通过java反射机制生成ConfigurableWebApplicationContext类对象,它就是springbean生成运行环境(BeanFactory容器
 
2. 刷新初始化webApplication
ConfigurableWebApplicationContext cwac = (ConfigurableWebApplicationContext) this.context;
configureAndRefreshWebApplicationContext(cwac,servletContext);
 
 
 
 
生成好spring上下文对象后,进入configureAndRefreshWebApplicationContext(ConfigurableWebApplicationContext wac, ServletContext sc)方法,主要执行代码如下:
 
wac.setServletContext(sc);
String configLocationParam = sc.getInitParameter(CONFIG_LOCATION_PARAM);
if (configLocationParam != null) {
wac.setConfigLocation(configLocationParam);//spring 上下文设置spring bean配置文件路径
}
 
ConfigurableEnvironment env = wac.getEnvironment();
if (envinstanceof ConfigurableWebEnvironment) {
((ConfigurableWebEnvironment) env).initPropertySources(sc, null);
}
customizeContext(sc, wac);
wac.refresh();
 
 
这里有一个注意的地方,ConfigurableEnvironment生成的地方,
wac.setConfigLocation(configLocationParam); 时根据 configLocationParam设置配置参数路径时就会初始化StandardServletEnvironmentConfigurableEnvironment的子类)
 
 
进入AbstractApplicationContext.refresh()方法
 
publicvoid 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) {
// Destroy already created singletons to avoid dangling resources.
destroyBeans();
// Reset 'active' flag.
cancelRefresh(ex);
 
// Propagate exception to caller.
throwex;
}finally {
// Reset common introspection caches in Spring's core, since we
// might not ever need metadata for singleton beans anymore...
resetCommonCaches();
}
}
}
 
 
 
(1)prepareRefresh()
// Initialize any placeholder property sources in the context environment
initPropertySources();
// Validate that all properties marked as required are resolvable
// see ConfigurablePropertyResolver#setRequiredProperties
getEnvironment().validateRequiredProperties();
 
(2) obtainFreshBeanFactory();此方法负责创建beanFactory并根据spring xml配置文件初始化得到BeanDefintions
 
 
 
 
这里主要看XmlWebApplicationContext类的loadBeanDefinitions方法
从上图看一看出,是如何一步一步的解析xml文件的
主要代码在NamespaceHandler,根据命名空间得到相应的处理器来解析相关配置文件中的标签tag
得到的handler为:org.springframework.context.config.ContextNamespaceHandler
其实就是从springjar包配置文件中获取的
publicclass ContextNamespaceHandler extends NamespaceHandlerSupport {
 
@Override
publicvoid init() {
registerBeanDefinitionParser("property-placeholder", new PropertyPlaceholderBeanDefinitionParser());
registerBeanDefinitionParser("property-override", new PropertyOverrideBeanDefinitionParser());
registerBeanDefinitionParser("annotation-config", new AnnotationConfigBeanDefinitionParser());
registerBeanDefinitionParser("component-scan", new ComponentScanBeanDefinitionParser());
registerBeanDefinitionParser("load-time-weaver", new LoadTimeWeaverBeanDefinitionParser());
registerBeanDefinitionParser("spring-configured", new SpringConfiguredBeanDefinitionParser());
registerBeanDefinitionParser("mbean-export", new MBeanExportBeanDefinitionParser());
registerBeanDefinitionParser("mbean-server", new MBeanServerBeanDefinitionParser());
}
 
}
 
应该可以明显看出,xml中的标签就是通过这些handler来处理的
通过handler中注册的parser来解析tag
 
下面再来看下是如何解析的
通过tag名称,得到相应的解析器并做相应的处理
 
 
 
上面实例就是解析property-placeholder标签的parser
 
 
 
 
回到refresh()方法,可以看到obtainFreshBeanFactory();其实已经干了大部分工作了,创建spring bean上下文beanFactory 并解析xml得到beanDefintion初始化上下文。
 
下一步执行prepareBeanFactory(beanFactory);方法
 
这个方法主要是对beanFactory做一些初始化工作
1)设置classLoader
2)设置SpEL表达式解析
3)设置ResourceEditorRegistrar(在获取bean中设置value
4)设置前置处理器
beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));
5)设置一些不需要autowiredbean
beanFactory.ignoreDependencyInterface(ApplicationContextAware.class);
ApplicationContextAware子类不通过autowired方式注入
6)设置和环境相关的beans
 
 
prepareBeanFactory之后执行postProcessBeanFactory
主要设置了一些前置处理器。
 
// Invoke factory processors registered as beans in the context.
invokeBeanFactoryPostProcessors(beanFactory);
 
后续就是注册资源文件,监听器,实例化一些非延迟加载的bean,最后广播相关事件 over
 
 
 
总结:
spring家族中所有的部件都是基于spring bean容器的,了解beanFactory上下文的结构和原理对理解spring十分重要,本文主要从整体上描述了spring 如何在web环境中初始化启动,从源码上给出了一个简要的流程描述,希望读者仔细阅读后能对spring bean容器有一个系统的了解。
 
 
 
 
参考:
2.http://www.cnblogs.com/RunForLove/p/5688731.html
分享到:
评论

相关推荐

    Spring Bean创建初始化流程.docx

    在Spring框架中,Bean的创建和初始化是IoC(Inversion of Control)容器的核心功能,这一过程涉及到多个步骤。以下是对Spring Bean创建初始化流程的详细解释: 1. **初始化ApplicationContext**: 开始时,通过`...

    springBean加载过程源码解析文档,附有代码类名和行数

    ApplicationContextInitializer 是 Spring 上下文初始化类,负责加载配置文件和注册 Bean。通过查看源码,我们可以发现 Spring 自动加载配置文件的代码。 SpringApplication 运行 SpringApplication 的 run 方法是...

    利用Spring Context上下文创建自定义对象

    在Spring应用中,Context通常通过`ApplicationContext`接口来实例化,如`ClassPathXmlApplicationContext`或`FileSystemXmlApplicationContext`,这些类用于加载XML配置文件并初始化bean。 创建自定义对象的基本...

    Spring Bean重复执行两次(实例被构造两次)问题分析

    6. **Bean的作用域**:默认情况下,Spring Bean的作用域是Singleton,意味着在整个应用上下文中只有一个实例。如果将Bean设置为Prototype,那么每次请求都会创建一个新的实例,可能导致重复执行。 7. **XML配置中的...

    第二十章 Spring 应用上下文生命周期(ApplicationContext Lifecycle)1

    在此阶段,ApplicationContext会初始化如MessageSource这样的内建Bean,提供消息国际化服务,以及初始化Spring事件广播器,使得事件驱动的通信成为可能。 7. **Spring 应用上下文刷新阶段** 刷新过程涉及Bean的...

    springmvc spring 两套上下文问题

    如果某个Bean需要访问到Spring的全局ApplicationContext,它可以实现这个接口,Spring会在初始化时自动注入ApplicationContext实例。这样,WebApplicationContext就可以访问到由全局ApplicationContext管理的Bean,...

    spring在@Bean注解中initMethod调用方法异步

    2. `AsyncProxyBeanPostProcessor`:此处理器可能用于创建代理对象,确保异步初始化方法在正确的上下文中执行。代理对象能够拦截调用并将其转换为异步操作。 3. `BeanDefinitionUtil`:这个工具类可能包含了对bean...

    Spring在web下启动流程学习笔记

    定制上下文可以通过提供上下文初始化器类来实现,这些类通过`contextInitializerClasses`属性定义。这些初始化器可以在ApplicationContext启动前对其进行自定义配置,增强了Spring的灵活性。 在启动上下文阶段,...

    在Servlet直接获取Spring框架中的Bean.docx

    在Web应用中,Spring通常会创建一个WebApplicationContext,它与Servlet上下文(ServletContext)关联。 **方法一:使用WebApplicationContextUtils** 在Servlet中,我们可以利用`WebApplicationContextUtils`工具...

    Spring中关于Bean的管理的课件

    在Spring框架中,Bean的管理是其核心特性之一,它涉及到Bean的创建、初始化、装配以及销毁等整个生命周期过程。本课件主要涵盖了以下几个关键知识点: 1. **控制反转(IoC)和依赖注入(DI)**:Spring的核心设计...

    普通类调用Spring bean对象

    1. **ApplicationContext**:这是Spring提供的一个接口,代表了Spring的上下文,包含了bean的定义和bean的实例。我们可以使用`ApplicationContext`来获取bean。例如: ```java ApplicationContext context = new ...

    Spring源代码解析(二):IoC容器在Web容器中的启动.doc

    当Web容器启动时,Spring的初始化过程会创建`XmlWebApplicationContext`实例,并调用`refresh()`方法来加载bean定义。这个过程主要由`loadBeanDefinitions()`方法完成,它使用`XmlBeanDefinitionReader`来解析XML...

    org.springframework.web-3.0.0.RC3.jar

    2. **RequestContextListener**:这个监听器帮助初始化和清理Web上下文,确保每个请求都有一个独立的上下文环境。 四、Spring Web服务 除了MVC,Spring Web还支持Web服务的创建和消费。在3.0.0.RC3版本中,Spring...

    在非spring注解类中使用spring容器中的bean_普通类中使用yml配置文件中的配置信息

    为了读取YAML配置,你需要在Spring Boot应用的启动类或者其他适当的初始化点,注册`@EnableConfigurationProperties`注解,指定配置属性类。例如,如果你有一个名为`ConfigProps`的类,其中包含了YAML文件中的属性:...

    Spring源码学习七:web应用自动装配Spring配置文件1

    `ContextLoaderListener`的`contextInitialized`方法主要负责调用`initWebApplicationContext`方法,该方法在`ContextLoader`类中实现,其作用是初始化Web环境下的Spring应用上下文(ApplicationContext)。...

    详解Spring中bean的作用域

    Spring2.0 以后,增加了 session、request、global session 三种专用于 Web 应用程序上下文的 Bean。因此,默认情况下 Spring2.0 现在有五种类型的 Bean。当然,Spring2.0对 Bean 的类型的设计进行了重构,并设计出...

    spring在web.xml中和在struts中的不同配置..pdf

    这种配置方式下,Spring的初始化和Bean管理是在Struts的Action上下文中完成的,而不是直接在`web.xml`中配置。 Struts2的Spring插件会在Struts配置文件(如struts.xml)中定义一个`&lt;package&gt;`,包含`&lt;interceptors&gt;...

    web.xml文件中配置(servlet, spring, filter, listenr)的加载顺序

    在`web.xml`中配置Listener时,其加载顺序通常发生在所有其他组件之前,因为它们经常用于初始化应用程序环境或配置Spring容器。 **示例代码:** ```xml org.springframework.web.context....

    spring-webmvc

    Spring Context作为一个全局的应用上下文,提供了加载配置、管理Bean、事件传播等功能。开发者可以通过ApplicationContext接口访问和操作Bean,同时也可以利用@PostConstruct和@PreDestroy注解来控制Bean的初始化和...

    Spring框架web项目实战全代码分享

    - `&lt;listener&gt;`:定义了一个`ContextLoaderListener`监听器,当Web应用启动时,它会读取`context-param`中指定的配置文件,初始化Spring应用上下文。 4. **创建`applicationContext.xml`**: 这是Spring的配置...

Global site tag (gtag.js) - Google Analytics