如果兩個(gè)插件出現(xiàn)雙向的獨(dú)立性關(guān)聯(lián)就形成了循環(huán)依賴,Dengues利用Eclipse擴(kuò)展點(diǎn)方式解決這個(gè)問(wèn)題。

        首先來(lái)介紹一下原理。Eclipse在啟動(dòng)的時(shí)候會(huì)將所有的擴(kuò)展點(diǎn)實(shí)現(xiàn)加載到一個(gè)注冊(cè)表里面,這里注冊(cè)的東西可以是一個(gè)類,就像是我們通過(guò)擴(kuò)展點(diǎn)的方式實(shí)現(xiàn)一個(gè)Viewer一樣,我們不僅要寫入相應(yīng)的icon還要寫入相關(guān)的指定的類。
            

            
        同樣道理,如果我們可以定義一個(gè)擴(kuò)展點(diǎn),在Eclipse啟動(dòng)的時(shí)候把實(shí)現(xiàn)了這個(gè)擴(kuò)展點(diǎn)的類加載到一個(gè)核心插件里。如果別的插件如果要用這個(gè)類的話,直接加入對(duì)之個(gè)核心插件的依賴不就可以了從而回避了對(duì)這個(gè)插件直接的依賴見下圖:

        
        在圖1里A插件要引用B插件里的類,同樣B插件也有需求要引用A插件里的類,這樣就造成了插件的循環(huán)依賴。現(xiàn)在利用擴(kuò)展點(diǎn),在A,B插件里實(shí)現(xiàn)一個(gè)定義于Core插件里的擴(kuò)展點(diǎn),在Eclispe啟動(dòng)的時(shí)候,實(shí)現(xiàn)了此擴(kuò)展點(diǎn)的類將可以被加載到Core插件里。通過(guò)Core的橋梁作用A、B插件便可以實(shí)現(xiàn)類的相互引用。這里A、B插件只是對(duì)Core有一個(gè)單向的依賴關(guān)系,通過(guò)core插件的幫助A與B之間可以相互調(diào),避免了直接的調(diào)用所以也就不會(huì)形成循環(huán)依賴了。

        一、擴(kuò)展點(diǎn)的定義:

        點(diǎn)擊進(jìn)入org.dengues.core插件的plugin.xml 文件,打開Extension Point標(biāo)簽,點(diǎn)Add加入一個(gè)擴(kuò)展點(diǎn)輸入如下信息:
        
        在Definition里加一個(gè)叫做Service的element,并加入兩條use欄為reuqired的屬性如下圖所示:

        

        其中serviceClass的Type要選成java,并且在Implements里定義一個(gè)接口,這個(gè)接口規(guī)定了這個(gè)擴(kuò)展點(diǎn)在實(shí)現(xiàn)的時(shí)候指定的類。這里為IDenguesService。其實(shí)接口里什么也沒(méi)方法也沒(méi)有定義,只是一個(gè)申明而已。
        

        

package org.dengues.core;

public interface IDenguesService {

    String ID 
= "org.dengues.commons.denguesService"//$NON-NLS-1$

    String SERVICE_CLASS 
= "serviceClass"//$NON-NLS-1$

    String SERVICE_ID 
= "serviceID"//$NON-NLS-1$
}


        
        二、實(shí)現(xiàn)擴(kuò)展點(diǎn)。具體怎么用一個(gè)擴(kuò)展點(diǎn),這里就不用多說(shuō)了,只重點(diǎn)介紹一下怎么實(shí)現(xiàn)IDenguesService類。我們以Dengues里的org.dengues.design.core插件為例。在org.dengues.core里我們我建一個(gè)IDenguesService的子接口IDesignerCoreService,并寫入我們要向其它plugin公開的方法。
        

public interface IDesignerCoreService extends IDenguesService {

    
public IComponentsFactory getComponentsFactory();

    
public IComponentFilesNaming getComponentFilesNaming();

    
public void initializeTemplates();

    
public ICodeGenerator getCodeGenerator(ICompProcess process);

    
public ICodeGenerator getCodeGenerator();

    
public IJavaETLProcessor getJavaProcessor(ICompProcess process);

    
public IJavaETLProcessor getJavaProcessor();

    
// public Action createStartHsqldbServer(String dbName);

    
public Action createStartHsqldbServer();

    
public boolean checkHsqldbConnection();

    
public void runSqlScript(IFile scriptFile);

    
public DatabaseContainer getHsqlDatabase() throws SQLException;

    
public Connection getCurrentConnection() throws SQLException, CoreException, ClassNotFoundException;
}


         以上這些方法就是org.dengues.designer.core這個(gè)插件想要對(duì)其它插件公開的方法了,它的實(shí)現(xiàn)自然會(huì)被寫入到這個(gè)插件里了。這段代碼很多,我們就不列在這里了,如果有興趣的朋友可以到我們Dengues的google svn去check out代碼。寫好對(duì)IDesignerCoreService的實(shí)現(xiàn)以后,我們就可以把它加入到事先我們定義好的擴(kuò)展點(diǎn)里了,見下圖:
        
        

        圖中的DesignerCoreService就是IDesingerCoreService的實(shí)現(xiàn)。好了,當(dāng)Eclipse啟動(dòng)的時(shí)候它就會(huì)把這個(gè)類加載到注冊(cè)表里了,我們可以從這個(gè)注冊(cè)里取到這個(gè)類了。那以后如果我們想從這個(gè)plugin里向外公開一些方法的話,就可以通過(guò)向IDesignerCoreService寫入相應(yīng)的方法,在DesignerCoreService里寫入相應(yīng)的實(shí)現(xiàn)就可以了。

        三、從注冊(cè)表里取出擴(kuò)展點(diǎn)的類。

        在org.dengues.core里我們寫了一個(gè)GlobalServiceFactory里面提供了相應(yīng)的代碼:

            

static {
        IExtensionRegistry registry 
= Platform.getExtensionRegistry();
        configurationElements 
= registry.getConfigurationElementsFor(IDenguesService.ID); //$NON-NLS-1$
    }


    
/**
     * Comment method "getService".Gets the specific IService.
     * 
     * 
@param klass the Service type you want to get
     * 
@return IService IService
     
*/

    
public IDenguesService getService(Class klass) {
        IDenguesService service 
= services.get(klass);
        
if (service == null{
            service 
= findService(klass);
            
if (service == null{
                
throw new RuntimeException("GlobalServiceRegister.ServiceNotRegistered" + klass.getName()); //$NON-NLS-1$
            }

            services.put(klass, service);
        }

        
return service;
    }


        如果我們要取剛才定義好的那個(gè)IDesignerCoreService的話,我們可以按如下方式取到:

    public IDesignerCoreService getDesignerCoreService() {
        IDenguesService service 
= GlobalServiceFactory.getDefault().getService(IDesignerCoreService.class);
        
return (IDesignerCoreService) service;
    }

        
        其實(shí)段代碼是寫在org.dengues.core插件里的CorePlugin里的,也就是說(shuō)在任何一個(gè)插件里只要加入了對(duì)org.dengues.core的依賴都可以通過(guò)CorePlguin.getDefault().getDesignerCoreService()來(lái)得到IDesignerCoreService的實(shí)例了。