瘋狂

          STANDING ON THE SHOULDERS OF GIANTS
          posts - 481, comments - 486, trackbacks - 0, articles - 1
            BlogJava :: 首頁 :: 新隨筆 :: 聯系 :: 聚合  :: 管理

          apache discovery

          Posted on 2010-09-04 11:34 瘋狂 閱讀(681) 評論(0)  編輯  收藏 所屬分類: java apache項目

          轉載:http://terrencexu.javaeye.com/blog/715982

          Discovery組件被用以查找可插拔接口的實現實例,它提供了一種通用的實例化這些實現的方式,而且可以管理單例(工廠)的生命周期。本質上來講,就是定位那些實現了給定Java接口的類,并實例化。除此之外,Discovery還可以用以在給定的classpath中查找并加載資源文件。

           

          Discovery組件在查找所有的實現類的時候需要預先將允許被查找的實現類配置到默認的配置文件中,默認的配置文件為:

          /META-INF/services/<YOUR Interface whole name including pkg name>, Discovery將依次加載該文件中配置的允許加載的實現類。

           

          下面將舉例說明:

          首先定義一個Interface:Action

          Java代碼 復制代碼
          1. package com.javaeye.terrencexu.discovery;   
          2.   
          3. public interface Action {   
          4.   
          5.     public String getName();   
          6.        
          7. }  

           

          然后在不同的包里分別實現Action接口,如下(請注意包名)

          Java代碼 復制代碼
          1. package com.javaeye.terrencexu.discovery.impl;   
          2.   
          3. import com.javaeye.terrencexu.discovery.Action;   
          4.   
          5. public class CreateAction implements Action {   
          6.   
          7.     @Override  
          8.     public String getName() {   
          9.         return "Create Action";   
          10.     }   
          11.   
          12. }  

           

          Java代碼 復制代碼
          1. package com.javaeye.terrencexu.discovery.impl;   
          2.   
          3. import com.javaeye.terrencexu.discovery.Action;   
          4.   
          5. public class DeleteAction implements Action {   
          6.   
          7.     @Override  
          8.     public String getName() {   
          9.         return "Delete Action";   
          10.     }   
          11.   
          12. }  

           

          Java代碼 復制代碼
          1. package com.javaeye.terrencexu.discovery.impl2;   
          2.   
          3. import com.javaeye.terrencexu.discovery.Action;   
          4.   
          5. public class AddAction implements Action {   
          6.   
          7.     @Override  
          8.     public String getName() {   
          9.         return "Add Action";   
          10.     }   
          11.   
          12. }  

           

          Java代碼 復制代碼
          1. package com.javaeye.terrencexu.discovery.impl2;   
          2.   
          3. import com.javaeye.terrencexu.discovery.Action;   
          4.   
          5. public class RemoveAction implements Action {   
          6.   
          7.     @Override  
          8.     public String getName() {   
          9.         return "Remove Action";   
          10.     }   
          11.   
          12. }  

           

          接下來將定義配置文件,按序定義允許被加載的實現類,該文件默認存在位置為/META-INF/services/,文件名為com.javaeye.terrencexu.discovery.Action,文件內容如下:

          Java代碼 復制代碼
          1. # Display in order   
          2.   
          3. com.javaeye.terrencexu.discovery.impl.CreateAction   
          4. com.javaeye.terrencexu.discovery.impl.DeleteAction   
          5. com.javaeye.terrencexu.discovery.impl2.AddAction  

           

          這樣所有的準備材料就都已經齊全了,接下來可以驗證一把了,如下:

          Java代碼 復制代碼
          1.  /**  
          2.  *  CreateAction/DeleteAction/AddAction have been defined in /META-INF/services/com.javaeye.terrencexu.discovery.Action  
          3.  *    
          4.  *  And the order is CreateAction > DeleteAction > AddAction  
          5.  */  
          6. @SuppressWarnings("unchecked")   
          7. public void testGetAllProviders() {   
          8.     String[] expectedResults = new String[] {"Create Action""Delete Action""Add Action"};   
          9.            
          10.     Enumeration<Action> enu = Service.providers(Action.class);   
          11.   
          12.     int count = 0;   
          13.     while (enu.hasMoreElements()) {   
          14.         Action action = enu.nextElement();   
          15.         assertTrue("The action name should be \"" + expectedResults[count] + "\", but actually is \"" + action.getName() + "\"",    
          16.                action.getName().equals(expectedResults[count]));   
          17.         count ++;   
          18.     }   
          19.            
          20.     assertEquals(count, expectedResults.length);   
          21. }  

           

          可以發現,因為RemoveAction沒有被配置到service文件中,所以將不會被加載,另外一點兒就是,配置文件中的定義順序即加載順序。

           

          除此之外,Discovery提供了singleton模式加載唯一實現,并且該實現將被緩存在cache中,除非通過顯示的調用release()方法釋放緩存,否則所有之后的調用,都將返回初次調用加載的Action。

          Java代碼 復制代碼
          1. public void testFindCreateAction() {   
          2.     try {   
          3.         // Load provider com.javaeye.terrencexu.discovery.impl.CreateAction   
          4.         Action createAction = (Action) DiscoverSingleton.find(Action.class, CreateAction.class.getName());   
          5.         assertEquals("Create Action", createAction.getName());   
          6.     } finally {   
          7.         DiscoverSingleton.release();   
          8.     }   
          9. }  

           

           

          還有一點需要說明的是,如果定義了默認的service文件,無論通過singleton模式加載的實現類有沒有被配置在service文件中,都將默認加載配置中文中的第一個Action,比如上文中的CreateAction。

          Java代碼 復制代碼
          1. public void testFindDeleteActionInConfig() {   
          2.     try {   
          3.         // Load provider com.javaeye.terrencexu.discovery.impl.CreateAction   
          4.         Action deleteAction = (Action) DiscoverSingleton.find(Action.class, DeleteAction.class.getName());   
          5.            
          6.         // As the default configuration file defines the CreateAction as the first element, so you will always get the CreateAction as singleton.    
          7.         assertEquals("Create Action", deleteAction.getName());   
          8.     } finally {   
          9.         DiscoverSingleton.release();   
          10.     }   
          11. }  

           

          那么如果必須使用service文件,又想通過singleton模式加載某特定的實現類該怎么辦呢?可以通過傳遞Properties到DiscoverSingleton中去改變它的行為,如下:

          Java代碼 復制代碼
          1. public void testFindDeleteActionWithProperty() {   
          2.     try {   
          3.         Properties props = new Properties();   
          4.         props.setProperty(Action.class.getName(), DeleteAction.class.getName());   
          5.            
          6.         // Load provider com.javaeye.terrencexu.discovery.impl.CreateAction   
          7.         Action deleteAction = (Action) DiscoverSingleton.find(Action.class, props);   
          8.         assertEquals("Delete Action", deleteAction.getName());   
          9.     } finally {   
          10.         DiscoverSingleton.release();   
          11.     }   
          12. }  

           

          除了加載類之外,很多情況下我們還想加載資源文件,比如在你的classpath下有一個配置文件為/conf/testResource,下面我們通過Discovery去加載該資源文件:

          Java代碼 復制代碼
          1. public void testFindResources() {   
          2.     ClassLoaders loaders = new ClassLoaders();   
          3.     ClassLoader cl = getClass().getClassLoader();   
          4.     if(cl != null) {   
          5.         loaders.put(getClass().getClassLoader(), true);   
          6.     } else {   
          7.         loaders.put(JDKHooks.getJDKHooks().getSystemClassLoader(), true);   
          8.     }   
          9.        
          10.     String name = "conf/testResource";   
          11.     DiscoverResources discovery = new DiscoverResources(loaders);   
          12.     ResourceIterator iter = discovery.findResources(name);   
          13.        
          14.     while(iter.hasNext()) {   
          15.         Resource resource = iter.nextResource();   
          16.         URL url = resource.getResource();   
          17.         System.out.println(url);   
          18.     }   
          19. }  

           

          Discovery還有其他一些功能這里就不在詳細的一一贅述了,可以參考http://commons.apache.org/discovery/index.html進一步詳細了解。

           

          下圖是我的例子的目錄結構,僅供參考:


          然后附件中有source code,僅供參考。


           

          主站蜘蛛池模板: 拜泉县| 富平县| 马龙县| 治多县| 鄂尔多斯市| 嵊泗县| 陈巴尔虎旗| 吕梁市| 林州市| 娄底市| 富锦市| 武城县| 商丘市| 五莲县| 乌兰察布市| 景德镇市| 上饶市| 滁州市| 白城市| 昌图县| 潼关县| 都昌县| 锦州市| 蒙自县| 蛟河市| 隆子县| 闸北区| 黄平县| 卓资县| 易门县| 唐山市| 九龙坡区| 壶关县| 鄱阳县| 梅州市| 咸丰县| 天等县| 晋宁县| 腾冲县| 聂荣县| 开江县|