Roller4.0.1中,使用了2个监听器:
<!-- Context Listeners --> <!-- 控制session的启动和关闭 --> <listener> <listener-class>org.apache.roller.weblogger.ui.core.RollerSession</listener-class> </listener> <!-- 初始化Roller web application/context --> <listener> <listener-class>org.apache.roller.weblogger.ui.core.RollerContext</listener-class> </listener> <!-- Tile的一个监听器 --> <listener> <listener-class>org.apache.tiles.web.startup.TilesListener</listener-class> </listener>
先说明一下RollerContext:
RollerContext 继承了 org.springframework.web.context.ContextLoaderListener
实现了 javax.servlet.ServletContextListerner
javax.servlet.ServletContextListerner是Listener接口之一,在container启动和关闭的时候,会调用ServletContextListerner,
Roller就是在ServletContextListerner中完成初始化的。
先把最后的总结提前,在RollerContext中的contextInitialized中完成
总结一下: 1. 首先设置一些最基本的参数, 2. 做启动的一些准备工作 : WebloggerStartup.prepare():完成对数据库和mail provider的确认 3. 随后进行最主要的工作: WebloggerFactory.bootstrap() : 将处理流程串联起来(trigger bootstrapping process):通过WebloggerFactory,得到WebloggerProvider,再通过WebloggerProvider,得到 Weblogger WebloggerFactory.getWeblogger().initialize():进行一系列的初始化(trigger initialization process),这个初始化也就是Weblogger在初始化 4. 如果有必要,初始化planet(参数 planet.aggregator.enable) 5. 初始化Acegi权限 6. 设置velocity模板引擎
首先完成spring的初始化过程,
然后设定资源上传的目录,保存在WebloggerConfig中(基本上所有的配置都从这个文件中获取)
开始最核心的操作了:
WebloggerStartup.prepare
在prepare中, 首先对DB和Mail Provider进行准备
DatabaseProvider、MailProvider
1. 对配置中的信息进行读取,进行测试
2. 随后对数据库的表进行校验,必须要有的表是否存在
isCreationRequired:对表rolleruser、userrole进行检查,只要表存在就可以了。
通过com.getMetaData().getTables进行
isUpgradeRequired:检测是否需要升级
这个是读取数据库中表roller_properties的名为roller.database.version的行
以及通过配置文件roller-version.properties中的ro.version
进行比较
在DB和邮件 Provider检查好以后,进行:
WebloggerFactory.bootstrap()
WebloggerFactory.getWeblogger().initialize()
WebloggerFactory.bootstrap()的过程,bootstrap(引导) Weblogger business tier
通过配置文件(类WebloggerConfig获取weblogger.provider.class配置 )获取WebloggerProvider实例
再调用WebloggerFactory中bootstrap(webloggerProvider)
bootstrap(webloggerProvider)其实就是把WebloggerProvider保存下来,同时调用WeblogProvider的bootstrap(),
WebloggerConfig同时读取3个配置文件:
缺省的配置文件:org.apache.roller.weblogger.config.roller.properties
客户化的配置: roller-customer.properties
JVM参数: roller.customer.config---程序中的注释是: external config file
前2个用getResourceAsStream方式进行加载
最后一个用:System.getProperty方式加载
然后对配置进行处理:读取config.expandedProperties的话,对这些属性进行expand,在重新设置回去,如果这些属性进行了配置的话 (用其他值进行替换,程序中用System.getProperties中的值进行替换)
同时也对log系统的配置进行初始化,读取以"log4j."开头的属性
在源码中,static {} 中有这么一段:
// we'll need this to get at our properties files in the classpath :是需要先加载到这个包吗?
Class config_class = Class.forName("org.apache.roller.weblogger.config.WebloggerConfig");
// first, lets load our default properties
InputStream is = config_class.getResourceAsStream(default_config);
config.load(is);
........
在配置文件中,
weblogger.provider.class配置成:org.apache.roller.weblogger.business.GuiceWebloggerProvider
GuiceWebloggerProvider构造函数也从配置文件中读取:guice.backend.module ,用于生成Weblogger
缺省配置是:org.apache.roller.weblogger.business.jpa.JPAWebloggerModule ,这是guice中的一个Module
下面的做法应该是guice中的要求了(不熟悉,看了以后再说)
在Provider.bootstrap获的Weblogger以后,Provider的初始化过程结束。
然后进入到weblogger的initialize过程中。
要弄清楚Weblogger的initialize,要了解WebloggerProvider获取到的Weblogger是怎么来的,这个要看一下guice了。
简单了解了一下guice,还是比较好了解的,-----先能看懂再说,使用guice开发以后再说,等要修改功能的时候必定要学会的。
看了一下,其实还是很简单的。通过@Inject来标记(看http://tech.it168.com/zt/guice/index.html有说明)
guice.backend.module中的代码如下:
public class JPAWebloggerModule implements Module { public void configure(Binder binder) { binder.bind(Weblogger.class).to(JPAWebloggerImpl.class); binder.bind(JPAPersistenceStrategy.class); binder.bind(org.apache.roller.weblogger.planet.business.jpa.JPARollerPlanetPersistenceStrategy.class); binder.bind(AutoPingManager.class).to( JPAAutoPingManagerImpl.class); binder.bind(BookmarkManager.class).to( JPABookmarkManagerImpl.class); binder.bind(PingQueueManager.class).to( JPAPingQueueManagerImpl.class); binder.bind(PingTargetManager.class).to( JPAPingTargetManagerImpl.class); binder.bind(PropertiesManager.class).to( JPAPropertiesManagerImpl.class); binder.bind(RefererManager.class).to( JPARefererManagerImpl.class); binder.bind(ThreadManager.class).to( JPAThreadManagerImpl.class); binder.bind(UserManager.class).to( JPAUserManagerImpl.class); binder.bind(WeblogManager.class).to( JPAWeblogManagerImpl.class); binder.bind(ReferrerQueueManager.class).to(ReferrerQueueManagerImpl.class); binder.bind(FileManager.class).to( FileManagerImpl.class); binder.bind(IndexManager.class).to( IndexManagerImpl.class); binder.bind(PluginManager.class).to( PluginManagerImpl.class); binder.bind(ThemeManager.class).to( ThemeManagerImpl.class); binder.bind(URLStrategy.class).to( MultiWeblogURLStrategy.class); } }
实现Weblogger接口的是: JPAWebloggerImpl.class ---- 完整的路径是: org.apache.roller.weblogger.business.jpa.JPAWebloggerImpl.class--这个是主要的实现者
JPAWebloggerImpl 继承: org.apache.roller.weblogger.business.WebloggerImpl,
WebloggerImpl 实现接口: org.apache.roller.weblogger.business.Weblogger
下面主要对initialize所作的工作进行分析:
首先是4个Manager的初始化:
getPropertiesManager().initialize(); // Manages global properties for Roller. getThemeManager().initialize(); // Manager interface for accessing Theme related objects. getThreadManager().initialize(); // Thread management for executing scheduled and asynchronous tasks. getIndexManager().initialize(); // Interface to Roller's Lucene-based search facility.
实现都在: org.apache.roller.weblogger.business.jpa中。
中间有一步是ping服务器,没有仔细看。
最后是进行一次db的flush。采用的就是JPA中最基本的方式:
在JPAWebloggerImpl中,使用的是:
public void flush() throws WebloggerException { this.strategy.flush(); }
strategy是:JPAPersistenceStrategy类型,它的flush为:
/** * Flush changes to the datastore, commit transaction, release em. * @throws org.apache.roller.weblogger.WebloggerException on any error */ public void flush() throws WebloggerException { try { EntityManager em = getEntityManager(true); em.getTransaction().commit(); } catch (PersistenceException pe) { throw new WebloggerException(pe); } }
就只有一个获取EntityManager,进行一次commit;
幸好前2天周末,才看了JPA的一些技术(非常可惜的是雨果丢了: http://www.360doc.com/content/091130/09/41237_10047630.html )
JPA获取到EntityManager,就会对数据库进行一次检查,如果没有表,会往数据库中建表。
注意到: 注释中写的“release em”,但是实际上没有释放em,这是怎么回事?(虽然有一个释放em的filter,但是这里所有的过程是在listener中进行的)
自此,Weblogger的所有动作完成了。
总结一下:
1. 首先设置一些最基本的参数,
2. 做启动的一些准备工作 : WebloggerStartup.prepare():完成对数据库和mail provider的确认
3. 随后进行最主要的工作:
WebloggerFactory.bootstrap() : 将处理流程串联起来(trigger bootstrapping process):通过WebloggerFactory,得到WebloggerProvider,再通过WebloggerProvider,得到Weblogger
WebloggerFactory.getWeblogger().initialize():进行一系列的初始化(trigger initialization process),这个初始化也就是Weblogger在初始化
4. 如果有必要,初始化planet(参数 planet.aggregator.enable)
5. 初始化Acegi权限
6. 设置velocity模板引擎