Liferay 启动过程分析3-处理启动事件(第三部分)

简介:

 

在配置完2个模板引擎之后,它就开始注册索引器:

 

(7)注册索引器:

 
 
  1. // Indexers 
  2.  
  3.         IndexerRegistryUtil.register(new MBIndexer()); 
  4.         IndexerRegistryUtil.register(new PluginPackageIndexer()); 

这里看出,这里注册两种索引器,一个是为MessageBoard注册索引器,一个是为所有的PluginPackage(portlet,layout-template,theme)注册索引器,他们都实现了Indexer接口,所以它必须能完成大多数Indexer的基本操作,比如查询,排序,重建索引,删除等,因为比较简单,就不说了。

 

(8)数据库升级器:

 
 
  1. // Upgrade 
  2.  
  3.         if (_log.isDebugEnabled()) { 
  4.             _log.debug("Upgrade database"); 
  5.         } 
  6.  
  7.         DBUpgrader.upgrade(); 

它会让DBUpgrader执行升级的动作,在DBUpgrader的upgrade()方法中。

首先,它禁用数据库的缓存:

 
 
  1. // Disable database caching before upgrade 
  2.  
  3.         if (_log.isDebugEnabled()) { 
  4.             _log.debug("Disable cache registry"); 
  5.         } 
  6.  
  7.         CacheRegistryUtil.setActive(false); 

CacheRegistryUtil的setActive()方法,最终会调用CacheRegistryImpl的setActive()方法:

 
 
  1. public void setActive(boolean active) { 
  2.         _active = active; 
  3.  
  4.         if (!active) { 
  5.             clear(); 
  6.         } 
  7.     } 

当传入false值时,它会调用CacheRegistryImpl的clear()方法:

 
 
  1. public void clear() { 
  2.         for (Map.Entry<String, CacheRegistryItem> entry : 
  3.                 _cacheRegistryItems.entrySet()) { 
  4.  
  5.             CacheRegistryItem cacheRegistryItem = entry.getValue(); 
  6.  
  7.             if (_log.isDebugEnabled()) { 
  8.                 _log.debug( 
  9.                     "Invalidating " + cacheRegistryItem.getRegistryName()); 
  10.             } 
  11.  
  12.             cacheRegistryItem.invalidate(); 
  13.         } 
  14.     } 

可以看出,禁用数据库缓存的本质是是调用所有cacheRegistryItem的invalidate()方法。

 

当禁用完数据库缓存之后,我们可以正式开始升级数据库,我们回到DBUpgrader类的

upgrader中,它首先获取buildNumber号:

 
 
  1. int buildNumber = ReleaseLocalServiceUtil.getBuildNumberOrCreate(); 

这个版本号,ReleaseLocalServiceUtil中进行了调用封装,最终来自ReleaseLocalServiceImpl类的getBuildNumberOrCreate()方法,它会从数据库中取得buildNumber:

 
 
  1. public int getBuildNumberOrCreate() 
  2.     throws PortalException, SystemException { 
  3.  
  4.     // Get release build number 
  5.  
  6. .. 
  7.     try { 
  8.         con = DataAccess.getConnection(); 
  9.  
  10.         ps = con.prepareStatement(_GET_BUILD_NUMBER); 
  11.  
  12.         ps.setLong(1, ReleaseConstants.DEFAULT_ID); 
  13.  
  14.         rs = ps.executeQuery(); 
  15.  
  16.         if (rs.next()) { 
  17.             int buildNumber = rs.getInt("buildNumber"); 
  18.  
  19.             if (_log.isDebugEnabled()) { 
  20.                 _log.debug("Build number " + buildNumber); 
  21.             } 
  22.  
  23.             testSupportsStringCaseSensitiveQuery(); 
  24.  
  25.             return buildNumber; 
  26.         } 
  27.     } 
  28.     catch (Exception e) { 
  29.         if (_log.isWarnEnabled()) { 
  30.             _log.warn(e.getMessage()); 
  31.         } 
  32.     } 
  33.     finally { 
  34.         DataAccess.cleanUp(con, ps, rs); 
  35.     } 
  36.  
  37.     // Create tables and populate with default data 
  38.  
  39.     if (GetterUtil.getBoolean( 
  40.             PropsUtil.get(PropsKeys.SCHEMA_RUN_ENABLED))) { 
  41.  
  42.         releaseLocalService.createTablesAndPopulate(); 
  43.  
  44.         testSupportsStringCaseSensitiveQuery(); 
  45.  
  46.         Release release = getRelease( 
  47.             ReleaseConstants.DEFAULT_SERVLET_CONTEXT_NAME, 
  48.             ReleaseInfo.getBuildNumber()); 
  49.  
  50.         return release.getBuildNumber(); 
  51.     } 
  52.     else { 
  53.         throw new NoSuchReleaseException( 
  54.             "The database needs to be populated"); 
  55.     } 

然后它会吧这个buildNumber和服务器的releaseNumber还有5.0.0进行比较,确保数据库的版本高于5.0.0,并且不高于服务器的版本号:

 
 
  1. if (buildNumber > ReleaseInfo.getBuildNumber()) { 
  2.     .. 
  3.  else if (buildNumber < ReleaseInfo.RELEASE_5_0_0_BUILD_NUMBER) { 
  4.             String msg = "You must first upgrade to Liferay Portal 5.0.0"
  5. }

一旦数据库版本号满足 5.0.0<=DB版本号<=服务器版本号,则DB就可以进行升级了。它先重新加载SQL语句:

 
 
  1. // Reload SQL 
  2.  
  3.     CustomSQLUtil.reloadCustomSQL(); 
  4.     SQLTransformer.reloadSQLTransformer(); 

这2个语句对应的内容都会先判断db的方言,然后选用正确的语句执行,第二个语句,主要执行的是Hibernate的HQL和JPA的JPQL之间的转换。

然后,它还会做一系列的数据库升级动作,就不一一展开了。

 

(9)初始化消息总线:

 
 
  1. // Messaging 
  2.  
  3.         if (_log.isDebugEnabled()) { 
  4.             _log.debug("Initialize message bus"); 
  5.         } 
  6.  
  7.         MessageBus messageBus = (MessageBus)PortalBeanLocatorUtil.locate( 
  8.             MessageBus.class.getName()); 
  9.         MessageSender messageSender = 
  10.             (MessageSender)PortalBeanLocatorUtil.locate( 
  11.                 MessageSender.class.getName()); 
  12.         SynchronousMessageSender synchronousMessageSender = 
  13.             (SynchronousMessageSender)PortalBeanLocatorUtil.locate( 
  14.                 SynchronousMessageSender.class.getName()); 
  15.  
  16.         MessageBusUtil.init( 
  17.             messageBus, messageSender, synchronousMessageSender); 

它会向ClassLoader所要MessageBus 和 MessageSender的对象:然后执行初始化动作。

 

(10)初始化ClusterExecutor,其实是初始化自身的集群节点信息(因为它不能假定自己是否在一个集群环境中,所以还是吧自己的节点信息初始化之)

 
 
  1. // Cluster executor 
  2.  
  3.     ClusterExecutorUtil.initialize(); 

它最终会调用ClusterExecutorImpl的initialize()方法:

 
 
  1. public void initialize() { 
  2.         if (!isEnabled()) { 
  3.             return
  4.         } 
  5.  
  6.         PortalUtil.addPortalPortEventListener(this); 
  7.  
  8.         _localAddress = new AddressImpl(_controlChannel.getLocalAddress()); 
  9.  
  10.         try { 
  11.             initLocalClusterNode(); 
  12.         } 
  13.         catch (SystemException se) { 
  14.             _log.error("Unable to determine local network address", se); 
  15.         } 
  16.  
  17.         ObjectValuePair<Address, ClusterNode> localInstance = 
  18.             new ObjectValuePair<Address, ClusterNode>( 
  19.                 _localAddress, _localClusterNode); 
  20.  
  21.         _liveInstances.put(localInstance, Long.MAX_VALUE); 
  22.  
  23.         _clusterNodeAddresses.put( 
  24.             _localClusterNode.getClusterNodeId(), _localAddress); 
  25.  
  26.         _clusterRequestReceiver.initialize(); 
  27.  
  28.         _scheduledExecutorService = Executors.newScheduledThreadPool( 
  29.             1
  30.             new NamedThreadFactory( 
  31.                 ClusterExecutorImpl.class.getName(), Thread.NORM_PRIORITY, 
  32.                 Thread.currentThread().getContextClassLoader())); 
  33.  
  34.         _scheduledExecutorService.scheduleWithFixedDelay( 
  35.             new HeartbeatTask(), 0
  36.             PropsValues.CLUSTER_EXECUTOR_HEARTBEAT_INTERVAL, 
  37.             TimeUnit.MILLISECONDS); 
  38.     } 

就不往下展开了。

 

(11)初始化定时器:

 
 
  1. // Scheduler 
  2.  
  3.     if (_log.isDebugEnabled()) { 
  4.         _log.debug("Initialize scheduler engine lifecycle"); 
  5.     } 
  6.  
  7.     SchedulerEngineUtil.initialize(); 

它会调用SchedulerEngineUtil的initialize()方法:

 
 
  1. public static void initialize() throws SchedulerException { 
  2.         _instance._initialize(); 
  3.  
  4.         SchedulerLifecycle schedulerLifecycle = new SchedulerLifecycle(); 
  5.  
  6.         schedulerLifecycle.registerPortalLifecycle(PortalLifecycle.METHOD_INIT); 
  7.     } 

从第02行跟踪下去,会发现它仍然是和集群相关的,它会去调用ClusterSchedulerEngine的initialize()方法,进而调用initMemoryClusteredJobs()方法,这里就不展开了:

 

 
 
  1. protected void initMemoryClusteredJobs() throws Exception { 
  2.         List<SchedulerResponse> schedulerResponses = 
  3.             (List<SchedulerResponse>)callMaster( 
  4.                 _getScheduledJobsMethodKey3, StorageType.MEMORY_CLUSTERED); 
  5.  
  6.         for (SchedulerResponse schedulerResponse : schedulerResponses) { 
  7.             Trigger oldTrigger = schedulerResponse.getTrigger(); 
  8.  
  9.             String jobName = schedulerResponse.getJobName(); 
  10.             String groupName = SchedulerEngineUtil.namespaceGroupName( 
  11.                 schedulerResponse.getGroupName(), StorageType.MEMORY_CLUSTERED); 
  12.  
  13.             Trigger newTrigger = TriggerFactoryUtil.buildTrigger( 
  14.                 oldTrigger.getTriggerType(), jobName, groupName, 
  15.                 oldTrigger.getStartDate(), oldTrigger.getEndDate(), 
  16.                 oldTrigger.getTriggerContent()); 
  17.  
  18.             schedulerResponse.setTrigger(newTrigger); 
  19.  
  20.             TriggerState triggerState = SchedulerEngineUtil.getJobState( 
  21.                 schedulerResponse); 
  22.  
  23.             Message message = schedulerResponse.getMessage(); 
  24.  
  25.             message.remove(JOB_STATE); 
  26.  
  27.             _memoryClusteredJobs.put( 
  28.                 getFullName(jobName, groupName), 
  29.                 new ObjectValuePair<SchedulerResponse, TriggerState>( 
  30.                     schedulerResponse, triggerState)); 
  31.         } 
  32.     } 

 





本文转自 charles_wang888 51CTO博客,原文链接:http://blog.51cto.com/supercharles888/905946,如需转载请自行联系原作者

目录
相关文章
|
Java Android开发 消息中间件
Android系统默认Home应用程序(Launcher)的启动过程源代码分析
转自 :http://blog.csdn.net/luoshengyang/article/details/6767736    在前面一篇文章中,我们分析了Android系统在启动时安装应用程序的过程,这些应用程序安装好之后,还需要有一个Home应用程序来负责把它们在桌面上展示出来,在Android系统中,这个默认的Home应用程序就是Launcher了,本文将详细分析Laun
2139 0
|
Java jenkins 持续交付
Spring Boot 项目脚本(启动、停止、重启、状态)
此脚本用来管理 SpringBoot 项目的进程状态。 有提示功能。 把脚本丢到项目文件夹, 添加执行权限即可。 如果 jenkins 使用这个脚本, 需要在 java -jar 命令前添加 BUILD_ID=dontKillMe , 不然 jenkins 会杀掉进程。
439 0
Spring Boot 项目脚本(启动、停止、重启、状态)