appfuse学习笔记(五)系统启动分析

1. web.xml中的配置
Spring配置文件及applicationContext监听器的配置

……
<!-- Context Configuration locations for Spring XML files -->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
classpath:/applicationContext-resources.xml
classpath:/applicationContext-dao.xml
classpath:/applicationContext-service.xml
classpath*:/applicationContext.xml
/WEB-INF/applicationContext*.xml
/WEB-INF/xfire-servlet.xml
/WEB-INF/security.xml
</param-value>
</context-param>
……
<listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<listener>
<listener-class>com.mycompany.app.webapp.listener.StartupListener</listener-class>
</listener>

2. ContextLoaderListener初始化applicationContext
当servlet容器启动时监听器ContextLoaderListener监听到ServletContextEvent事件,调用
contextInitialized方法
org.springframework.web.context.ContextLoaderListener

private ContextLoader contextLoader;
public void contextInitialized(ServletContextEvent event) {
this.contextLoader = createContextLoader();
//初始化WebApplicationContext
this.contextLoader.initWebApplicationContext(event.getServletContext());
}

在contextInitialized方法中调用了contextLoader的
initWebApplicationContext(event.getServletContext())方法
下面就来看contextLoader如何做的初始化
org.springframework.web.context.ContextLoader

private WebApplicationContext context;
public WebApplicationContext initWebApplicationContext(ServletContext servletContext)
throws IllegalStateException, BeansException {
……
servletContext.log("Initializing Spring root WebApplicationContext");
……
try {
……
this.context = createWebApplicationContext(servletContext, parent);
……
return this.context;
}
……
}

启动tomcat时控制台中输出的
“信息:Initializing Spring root WebApplicationContext”
即为此时输出
在initWebApplicationContext方法中通过
createWebApplicationContext(servletContext, parent)
方法创建了WebApplicationContext context对象
再看如何创建的WebApplicationContext
org.springframework.web.context.ContextLoader

public static final String CONFIG_LOCATION_PARAM = "contextConfigLocation";
protected WebApplicationContext createWebApplicationContext(
ServletContext servletContext, ApplicationContext parent) throws BeansException {
//使用serlcetContext从web.xml中得到配置的contextClass,如果没有则得到默认的contextClass
Class contextClass = determineContextClass(servletContext);
if (!ConfigurableWebApplicationContext.class.isAssignableFrom(contextClass)) {
throw new ApplicationContextException("Custom context class [" + contextClass.getName() +
"] is not of type [" + ConfigurableWebApplicationContext.class.getName() + "]");
}
ConfigurableWebApplicationContext wac =
(ConfigurableWebApplicationContext) BeanUtils.instantiateClass(contextClass);
……
//使用serlcetContext从web.xml中得到spring相关初始化配置参数
wac.setConfigLocation(servletContext.getInitParameter(CONFIG_LOCATION_PARAM));
……
return wac;
}

再看如何得到的contextClass
org.springframework.web.context.ContextLoader

private static final String DEFAULT_STRATEGIES_PATH = "ContextLoader.properties";
private static final Properties defaultStrategies;
static {
// Load default strategy implementations from properties file.
// This is currently strictly internal and not meant to be customized
// by application developers.
try {
ClassPathResource resource = new ClassPathResource(DEFAULT_STRATEGIES_PATH, ContextLoader.class);
defaultStrategies = PropertiesLoaderUtils.loadProperties(resource);
}
catch (IOException ex) {
throw new IllegalStateException("Could not load 'ContextLoader.properties': " + ex.getMessage());
}
}
public static final String CONTEXT_CLASS_PARAM = "contextClass";
protected Class determineContextClass(ServletContext servletContext) throws ApplicationContextException {
//web.xml中没有配置contextClass,所以这里将得到空
String contextClassName = servletContext.getInitParameter(CONTEXT_CLASS_PARAM);
if (contextClassName != null) {
try {
return ClassUtils.forName(contextClassName);
}
catch (ClassNotFoundException ex) {
throw new ApplicationContextException(
"Failed to load custom context class [" + contextClassName + "]", ex);
}
}
else {
// contextClassName == null, 将执行这里的方法
contextClassName = defaultStrategies.getProperty(WebApplicationContext.class.getName());
try {
return ClassUtils.forName(contextClassName, ContextLoader.class.getClassLoader());
}
catch (ClassNotFoundException ex) {
throw new ApplicationContextException(
"Failed to load default context class [" + contextClassName + "]", ex);
}
}
}

这里首先会去web.xml中查找有无配置项,没有的话将从配置文件中读取配置项
从源码中可以看到配置文件设置为” ContextLoader.properties”
要读取的配置项为WebApplicationContext.class.getName()
找到org/springframework/web/context/ ContextLoader.properties
# Default WebApplicationContext implementation class for ContextLoader.
# Used as fallback when no explicit context implementation has been specified as context-param.
# Not meant to be customized by application developers.

org.springframework.web.context.WebApplicationContext=org.springframework.web.context.support.XmlWebApplicationContext
所以最终在ContextLoaderListener中我们初始化得到的是XmlWebApplicationContext对象
3. StartupListener启动系统
当servlet容器启动时监听器StartupListener监听到ServletContextEvent事件,调用
contextInitialized方法
com.mycompany.app.webapp.listener.StartupListener

public void contextInitialized(ServletContextEvent event) {
log.debug("Initializing context...");
ServletContext context = event.getServletContext();
……
setupContext(context);
}
public static void setupContext(ServletContext context) {
ApplicationContext ctx = WebApplicationContextUtils.getRequiredWebApplicationContext(context);
LookupManager mgr = (LookupManager) ctx.getBean("lookupManager");
// get list of possible roles
context.setAttribute(Constants.AVAILABLE_ROLES, mgr.getAllRoles());
log.debug("Drop-down initialization complete [OK]");
}

下面先来看spring的配置
在applicationContext-service.xml中配置了bean “lookupManager”

<bean id="lookupManager" class="com.mycompany.app.service.impl.LookupManagerImpl">
<property name="lookupDao" ref="lookupDao"/>
</bean>

在applicationContext-dao.xml中配置了bean “lookupDao”

<bean id="lookupDao" class="com.mycompany.app.dao.hibernate.LookupDaoHibernate">
<property name="sessionFactory" ref="sessionFactory"/>
</bean>

同样在applicationContext-dao.xml中配置了bean “sessionFactory”

<bean id="sessionFactory" class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
<property name="dataSource" ref="dataSource"/>
<property name="configLocation" value="classpath:hibernate.cfg.xml"/>
<property name="hibernateProperties">
<value>
hibernate.dialect=${hibernate.dialect}
hibernate.query.substitutions=true 'Y', false 'N'
hibernate.cache.use_second_level_cache=true
hibernate.cache.provider_class=org.hibernate.cache.EhCacheProvider
</value>
<!-- Turn batching off for better error messages under PostgreSQL -->
<!-- hibernate.jdbc.batch_size=0 -->
</property>
</bean>

在这里指定了hibernate的配置文件和相关属性设置
<!—Hibernate SQL方言属性设置-->
hibernate.dialect=${hibernate.dialect}
<!—指定保存到数据库时true和false用Y和N代替 -->
hibernate.query.substitutions=true 'Y', false 'N'
<!—启用二级缓存-->
hibernate.cache.use_second_level_cache=true
<!—二级缓存的实现类-->
hibernate.cache.provider_class=org.hibernate.cache.EhCacheProvider

然后在applicationContext-resources.xml中配置了bean “dataSource”

<bean id="dataSource"
class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
<property name="driverClassName" value="${jdbc.driverClassName}"/>
<property name="url" value="${jdbc.url}"/>
<property name="username" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
<property name="maxActive" value="100"/>
<property name="maxWait" value="1000"/>
<property name="poolPreparedStatements" value="true"/>
<property name="defaultAutoCommit" value="true"/>
</bean>

这里使用了apache的dbcp来做的数据库连接池

配置文件先看到这里,回过头来再看
com.mycompany.app.webapp.listener.StartupListener

public static void setupContext(ServletContext context) {
ApplicationContext ctx = WebApplicationContextUtils.getRequiredWebApplicationContext(context);
LookupManager mgr = (LookupManager) ctx.getBean("lookupManager");
// get list of possible roles
context.setAttribute(Constants.AVAILABLE_ROLES, mgr.getAllRoles());
log.debug("Drop-down initialization complete [OK]");
}

在这里得到了所有的角色,以备访问时使用
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值