天天看點

Liferay 啟動過程分析3-處理啟動事件(第三部分)

在配置完2個模闆引擎之後,它就開始注冊索引器:

(7)注冊索引器:

// Indexers 

        IndexerRegistryUtil.register(new MBIndexer()); 

        IndexerRegistryUtil.register(new PluginPackageIndexer()); 

這裡看出,這裡注冊兩種索引器,一個是為MessageBoard注冊索引器,一個是為所有的PluginPackage(portlet,layout-template,theme)注冊索引器,他們都實作了Indexer接口,是以它必須能完成大多數Indexer的基本操作,比如查詢,排序,重建索引,删除等,因為比較簡單,就不說了。

(8)資料庫更新器:

// Upgrade 

        if (_log.isDebugEnabled()) { 

            _log.debug("Upgrade database"); 

        } 

        DBUpgrader.upgrade(); 

它會讓DBUpgrader執行更新的動作,在DBUpgrader的upgrade()方法中。

首先,它禁用資料庫的緩存:

// Disable database caching before upgrade 

            _log.debug("Disable cache registry"); 

        CacheRegistryUtil.setActive(false); 

CacheRegistryUtil的setActive()方法,最終會調用CacheRegistryImpl的setActive()方法:

public void setActive(boolean active) { 

        _active = active; 

        if (!active) { 

            clear(); 

    } 

當傳入false值時,它會調用CacheRegistryImpl的clear()方法:

public void clear() { 

        for (Map.Entry<String, CacheRegistryItem> entry : 

                _cacheRegistryItems.entrySet()) { 

            CacheRegistryItem cacheRegistryItem = entry.getValue(); 

            if (_log.isDebugEnabled()) { 

                _log.debug( 

                    "Invalidating " + cacheRegistryItem.getRegistryName()); 

            } 

            cacheRegistryItem.invalidate(); 

可以看出,禁用資料庫緩存的本質是是調用所有cacheRegistryItem的invalidate()方法。

當禁用完資料庫緩存之後,我們可以正式開始更新資料庫,我們回到DBUpgrader類的

upgrader中,它首先擷取buildNumber号:

int buildNumber = ReleaseLocalServiceUtil.getBuildNumberOrCreate(); 

這個版本号,ReleaseLocalServiceUtil中進行了調用封裝,最終來自ReleaseLocalServiceImpl類的getBuildNumberOrCreate()方法,它會從資料庫中取得buildNumber:

public int getBuildNumberOrCreate() 

    throws PortalException, SystemException { 

    // Get release build number 

.. 

    try { 

        con = DataAccess.getConnection(); 

        ps = con.prepareStatement(_GET_BUILD_NUMBER); 

        ps.setLong(1, ReleaseConstants.DEFAULT_ID); 

        rs = ps.executeQuery(); 

        if (rs.next()) { 

            int buildNumber = rs.getInt("buildNumber"); 

                _log.debug("Build number " + buildNumber); 

            testSupportsStringCaseSensitiveQuery(); 

            return buildNumber; 

    catch (Exception e) { 

        if (_log.isWarnEnabled()) { 

            _log.warn(e.getMessage()); 

    finally { 

        DataAccess.cleanUp(con, ps, rs); 

    // Create tables and populate with default data 

    if (GetterUtil.getBoolean( 

            PropsUtil.get(PropsKeys.SCHEMA_RUN_ENABLED))) { 

        releaseLocalService.createTablesAndPopulate(); 

        testSupportsStringCaseSensitiveQuery(); 

        Release release = getRelease( 

            ReleaseConstants.DEFAULT_SERVLET_CONTEXT_NAME, 

            ReleaseInfo.getBuildNumber()); 

        return release.getBuildNumber(); 

    else { 

        throw new NoSuchReleaseException( 

            "The database needs to be populated"); 

然後它會吧這個buildNumber和伺服器的releaseNumber還有5.0.0進行比較,確定資料庫的版本高于5.0.0,并且不高于伺服器的版本号:

if (buildNumber > ReleaseInfo.getBuildNumber()) { 

    .. 

 else if (buildNumber < ReleaseInfo.RELEASE_5_0_0_BUILD_NUMBER) { 

            String msg = "You must first upgrade to Liferay Portal 5.0.0"; 

}

一旦資料庫版本号滿足 5.0.0<=DB版本号<=伺服器版本号,則DB就可以進行更新了。它先重新加載SQL語句:

// Reload SQL 

    CustomSQLUtil.reloadCustomSQL(); 

    SQLTransformer.reloadSQLTransformer(); 

這2個語句對應的内容都會先判斷db的方言,然後選用正确的語句執行,第二個語句,主要執行的是Hibernate的HQL和JPA的JPQL之間的轉換。

然後,它還會做一系列的資料庫更新動作,就不一一展開了。

(9)初始化消息總線:

// Messaging 

            _log.debug("Initialize message bus"); 

        MessageBus messageBus = (MessageBus)PortalBeanLocatorUtil.locate( 

            MessageBus.class.getName()); 

        MessageSender messageSender = 

            (MessageSender)PortalBeanLocatorUtil.locate( 

                MessageSender.class.getName()); 

        SynchronousMessageSender synchronousMessageSender = 

            (SynchronousMessageSender)PortalBeanLocatorUtil.locate( 

                SynchronousMessageSender.class.getName()); 

        MessageBusUtil.init( 

            messageBus, messageSender, synchronousMessageSender); 

它會向ClassLoader所要MessageBus 和 MessageSender的對象:然後執行初始化動作。

(10)初始化ClusterExecutor,其實是初始化自身的叢集節點資訊(因為它不能假定自己是否在一個叢集環境中,是以還是吧自己的節點資訊初始化之)

// Cluster executor 

    ClusterExecutorUtil.initialize(); 

它最終會調用ClusterExecutorImpl的initialize()方法:

public void initialize() { 

        if (!isEnabled()) { 

            return; 

        PortalUtil.addPortalPortEventListener(this); 

        _localAddress = new AddressImpl(_controlChannel.getLocalAddress()); 

        try { 

            initLocalClusterNode(); 

        catch (SystemException se) { 

            _log.error("Unable to determine local network address", se); 

        ObjectValuePair<Address, ClusterNode> localInstance = 

            new ObjectValuePair<Address, ClusterNode>( 

                _localAddress, _localClusterNode); 

        _liveInstances.put(localInstance, Long.MAX_VALUE); 

        _clusterNodeAddresses.put( 

            _localClusterNode.getClusterNodeId(), _localAddress); 

        _clusterRequestReceiver.initialize(); 

        _scheduledExecutorService = Executors.newScheduledThreadPool( 

            1, 

            new NamedThreadFactory( 

                ClusterExecutorImpl.class.getName(), Thread.NORM_PRIORITY, 

                Thread.currentThread().getContextClassLoader())); 

        _scheduledExecutorService.scheduleWithFixedDelay( 

            new HeartbeatTask(), 0, 

            PropsValues.CLUSTER_EXECUTOR_HEARTBEAT_INTERVAL, 

            TimeUnit.MILLISECONDS); 

就不往下展開了。

(11)初始化定時器:

// Scheduler 

    if (_log.isDebugEnabled()) { 

        _log.debug("Initialize scheduler engine lifecycle"); 

    SchedulerEngineUtil.initialize(); 

它會調用SchedulerEngineUtil的initialize()方法:

public static void initialize() throws SchedulerException { 

        _instance._initialize(); 

        SchedulerLifecycle schedulerLifecycle = new SchedulerLifecycle(); 

        schedulerLifecycle.registerPortalLifecycle(PortalLifecycle.METHOD_INIT); 

從第02行跟蹤下去,會發現它仍然是和叢集相關的,它會去調用ClusterSchedulerEngine的initialize()方法,進而調用initMemoryClusteredJobs()方法,這裡就不展開了:

protected void initMemoryClusteredJobs() throws Exception { 

        List<SchedulerResponse> schedulerResponses = 

            (List<SchedulerResponse>)callMaster( 

                _getScheduledJobsMethodKey3, StorageType.MEMORY_CLUSTERED); 

        for (SchedulerResponse schedulerResponse : schedulerResponses) { 

            Trigger oldTrigger = schedulerResponse.getTrigger(); 

            String jobName = schedulerResponse.getJobName(); 

            String groupName = SchedulerEngineUtil.namespaceGroupName( 

                schedulerResponse.getGroupName(), StorageType.MEMORY_CLUSTERED); 

            Trigger newTrigger = TriggerFactoryUtil.buildTrigger( 

                oldTrigger.getTriggerType(), jobName, groupName, 

                oldTrigger.getStartDate(), oldTrigger.getEndDate(), 

                oldTrigger.getTriggerContent()); 

            schedulerResponse.setTrigger(newTrigger); 

            TriggerState triggerState = SchedulerEngineUtil.getJobState( 

                schedulerResponse); 

            Message message = schedulerResponse.getMessage(); 

            message.remove(JOB_STATE); 

            _memoryClusteredJobs.put( 

                getFullName(jobName, groupName), 

                new ObjectValuePair<SchedulerResponse, TriggerState>( 

                    schedulerResponse, triggerState)); 

本文轉自 charles_wang888 51CTO部落格,原文連結:http://blog.51cto.com/supercharles888/905946,如需轉載請自行聯系原作者