OSGI服务发布和导入的自主实现—OSGI+Spring+Hibernate+...完美解决方案[非SpringDM]之二

                                 OSGI服务发布和导入的自主实现

             —OSGI+Spring+Hibernate+...完美解决方案[SpringDM]之二

 

 

 

 

 

 

 

 

OSGI+Spring+Hibernate+...完美解决方案[SpringDM]一文中,我提出了非SpringDMOSGI下使用Spring的解决方案。

本文是该文的姐妹篇,讲解在“OSGI+Spring+Hibernate+...完美解决方案[SpringDM]”下的OSGI服务的发布和导入的实现。

 

 

 

OSGI服务的发布

OSGI下服务的发布,仍然和SpringDM下的相同。

如:

 

<service ref="beanToPublish" interface="com.xyz.MessageService"/>

 

<service id="myServiceRegistration" ref="beanToPublish"

interface="com.xyz.MessageService"/>

 

<osgi:service interface="com.xyz.MessageService">

<bean class="SomeClass">

...

</bean>

</osgi:service>

 

<osgi:service ref="beanToBeExported" interface="com.xyz.MessageService"/>

<bean id="beanToBeExported" scope="bundle" class="com.xyz.MessageServiceImpl"/>

   

    完全相同。不需改变。

 

 

我一向不喜欢自制Spring标签,如上面的osgi:service

自制Spring标签,虽然看上去挺酷,很专业。但是确实增加了我们用户的学习强度。你必须看文档才能知道该怎样使用这些千奇百怪的标签。

 

我还是喜欢直接使用<bean>标签。实际上,SpringDM中负责注册服务的类是:org.springframework.osgi.service.exporter.support.OsgiServiceFactoryBean类。

因此,我们可以这样注册OSGI服务:

 

1

<bean  id="userBySessionServiceOsgiService" class="org.springframework.osgi.service.exporter.support.OsgiServiceFactoryBean">

       <property name="target">

          <ref bean="userBySessionService"/>

       </property>

       <property name="interfaces">

          <util:list>

             <value>com.withub.gis.server.login.IUserBySessionService</value>

          </util:list>

       </property>

   </bean>

 

2

    <bean  id="loginWSSecurityOsgiService" class="org.springframework.osgi.service.exporter.support.OsgiServiceFactoryBean">

       <property name="target">

          <ref bean="loginWSSecurity"/>

       </property>

       <property name="interfaces">

          <util:list>

             <value>com.withub.gis.server.login.ILoginWSSecurity</value>

          </util:list>

       </property>

   </bean>

 

 

 

  

 

OSGI服务的导入

在我的解决方案下,再使用SpringDM的导入服务的方式就不行了,会报错。这应该是SpringDM内部实现造成的。

SpringDM下的org.springframework.osgi.service.importer.support. OsgiServiceProxyFactoryBean导入一个服务。

OsgiServiceCollectionProxyFactoryBean导入多个服务。

 

我们需要编写自己的导入OSGI服务的类

 

   

导入OSGI Service的类

    这是自己独立于SpringDMOSGI服务导入类。

 

/**

 *

 */

package com.withub.gis.osgi.util.springSupport.importService;

 

import java.util.ArrayList;

import java.util.List;

import java.util.Map;

import java.util.Set;

 

import org.osgi.framework.BundleContext;

import org.osgi.framework.Constants;

import org.osgi.framework.ServiceReference;

import org.osgi.util.tracker.ServiceTracker;

 

/**

 * @author 沈东良 Edward Shen [email protected]

 *

 */

public class ImportOsgiServiceFactory implements IImportOsgiServiceFactory {

       /* (non-Javadoc)

        * @see com.withub.gis.osgi.util.springSupport.importService.IImportOsgiServiceFactory#getService()

        */

       public Object getService(){

              Object[] services=this.getServices();

              if(services.length>=1){

                     return services[0];

              }else{

                     return null;

              }            

       }

      

       public static int DefaultRetryTimes=1;

       public static int DefaultWaitTime=1000;

      

       private int retryTimes=DefaultRetryTimes;

       private int waitTime=DefaultWaitTime;

       public int getRetryTimes() {

              return retryTimes;

       }

 

       public void setRetryTimes(int retryTimes) {

              this.retryTimes = retryTimes;

       }

       public int getWaitTime() {

              return waitTime;

       }

 

 

       public void setWaitTime(int waitTime) {

              this.waitTime = waitTime;

       }

 

 

       /* (non-Javadoc)

        * @see com.withub.gis.osgi.util.springSupport.importService.IImportOsgiServiceFactory#getServices()

        */

       public Object[] getServices(){

              List<ServiceReference> all=new ArrayList<ServiceReference>();

           String interface0=this.interfaces[0];

                     ServiceTracker serviceTracker=new ServiceTracker(this.bundleContext,interface0 , null);

                     serviceTracker.open();

                    

                     ServiceReference[] serviceReferences=serviceTracker.getServiceReferences();

                    

                     if(serviceReferences==null && this.retryTimes>0){

                            this.retryTimes--;

                            try {

                                   Thread.sleep(this.getWaitTime());

                            } catch (InterruptedException e) {

                                   // TODO Auto-generated catch block

                                   e.printStackTrace();

                            }

                            this.getServices();

                     }

                      

                     for(ServiceReference serviceReference:serviceReferences){

                            String[] objectClasses=(String[]) serviceReference.getProperty(Constants.OBJECTCLASS);

                            if(equal(this.interfaces,objectClasses)){

                                   all.add(serviceReference);

                            }

                     }

                    

                    

                     if(this.map!=null){

                            for(ServiceReference serviceReference:all){

                                   boolean upToGrade=true;

                                    Set<Map.Entry<String,Object>> entrySet=map.entrySet();

                                    for(Map.Entry<String,Object> entry:entrySet){

                                           if(serviceReference.getProperty(entry.getKey())==null){

                                                  if(entry.getValue()!=null){

                                                         upToGrade=false;

                                                         break;

                                                  }

                                           }else{

                                           

                                              if(!serviceReference.getProperty(entry.getKey()).equals(entry.getValue())){

                                                     upToGrade=false;

                                                     break;

                                              }

                                           }

                                           

                                    }

                                   if(upToGrade==false){

                                          all.remove(serviceReference);

                                         

                                   }

                            }

                           

                     }

                    

                     List allServices=new ArrayList();

                for(ServiceReference serviceReference:all){

                       allServices.add(this.bundleContext.getService(serviceReference));

                      

                } 

      

              return allServices.toArray();

       }

      

      

       private boolean equal(String[] interfaces, String[] objectClasses) {

              // TODO Auto-generated method stub

             

              for(String interface0:interfaces){

                     boolean yes=false;

                     for(String clazz:objectClasses){

                            if(interface0.equals(clazz)){

                                   yes=true;

                                   break;

                            }

                           

                     }

                     if(!yes){

                            return false;

                     }

              }

             

             

             

             

              return true;

             

             

             

       }

 

       private BundleContext bundleContext;

       private Map<String,Object> map;

 

      

       /**

        *

        */

       private String[] interfaces;

      

 

       /**

        *

        */

       public ImportOsgiServiceFactory() {

              // TODO Auto-generated constructor stub

       }

       public ImportOsgiServiceFactory(BundleContext bundleContext,String[] interfaces,Map<String,Object> map) {

              // TODO Auto-generated constructor stub

              this.bundleContext=bundleContext;

              this.interfaces=interfaces;

              this.map=map;

       }

 

       /**

        * @param args

        */

       public static void main(String[] args) {

              // TODO Auto-generated method stub

 

       }

 

       public BundleContext getBundleContext() {

              return bundleContext;

       }

 

       public void setBundleContext(BundleContext bundleContext) {

              this.bundleContext = bundleContext;

       }

 

       public String[] getInterfaces() {

              return interfaces;

       }

 

       public void setInterfaces(String[] interfaces) {

              this.interfaces = interfaces;

       }

 

       public Map getMap() {

              return map;

       }

 

       public void setMap(Map map) {

              this.map = map;

       }

 

      

 

}

 

 

使用的方法

下面给出一个使用的例子

 

1,使用Activator

package com.withub.gis.client.app.plugin;

 

import org.apache.commons.logging.Log;

import org.apache.commons.logging.LogFactory;

import org.eclipse.ui.plugin.AbstractUIPlugin;

import org.osgi.framework.BundleContext;

import org.springframework.osgi.context.DelegatedExecutionOsgiBundleApplicationContext;

 

import com.withub.gis.client.app.context.GISApplicationContext;

import com.withub.gis.osgi.util.springSupport.StandAloneOsgiApplicationContextCreator;

import com.withub.gis.server.startDependency.WithubGISServicStartDependency;

 

/**

 * The activator class controls the plug-in life cycle

沈东良

 */

public class Activator extends AbstractUIPlugin {

 

       // The plug-in ID

       public static final String PLUGIN_ID = "com.withub.gis.client.app";

 

       // The shared instance

       private static Activator plugin;

         private DelegatedExecutionOsgiBundleApplicationContext applicationContext;

 

              public DelegatedExecutionOsgiBundleApplicationContext getApplicationContext() {

                     return applicationContext;

              }

       /**

        * The constructor

        */

       public Activator() {

       }

 

       /*

        * (non-Javadoc)

        * @see org.eclipse.ui.plugin.AbstractUIPlugin#start(org.osgi.framework.BundleContext)

        */

       public void start(BundleContext context) throws Exception {

              super.start(context);

              plugin = this;

              /**

               * WithubGISServicStartDependency这个类是依赖的插件Service发布出来的一个类。

               * 如果使用这个类,就意味着Service插件必须被启动。

               * 这就使Service插件先发布我们需要的OSGI Service。保证了使用。

               */

              WithubGISServicStartDependency withubGISServicStartDependency=new WithubGISServicStartDependency();

              System.out.println(Activator.PLUGIN_ID+" Startup!!");

              GISApplicationContext.getInstance().setBundleContext(context);

             

              String[] configFiles = new String[] { "spring/bean.xml", "classpath:spring/osgi.xml" };

 

              StandAloneOsgiApplicationContextCreator standAloneOsgiApplicationContextCreator = new StandAloneOsgiApplicationContextCreator(

                            configFiles);

              try {

                     this.applicationContext = standAloneOsgiApplicationContextCreator.createApplicationContext(context);

                     //applicationContext.refresh();

              } catch (Exception e1) {

                     // TODO Auto-generated catch block

                     e1.printStackTrace();

              }

 

              System.out.println("Spring ApplicationContext  Startup!!");

       }

 

       /*

        * (non-Javadoc)

        * @see org.eclipse.ui.plugin.AbstractUIPlugin#stop(org.osgi.framework.BundleContext)

        */

       public void stop(BundleContext context) throws Exception {

              plugin = null;

              super.stop(context);

              System.out.println(Activator.PLUGIN_ID+"  Shutdown!!");

       }

 

       /**

        * Returns the shared instance

        *

        * @return the shared instance

        */

       public static Activator getDefault() {

              return plugin;

       }

       private ClassLoader classLoader = this.getClass().getClassLoader();

       private Log log = LogFactory.getLog(this.getClass());

      

      

 

 

       public ClassLoader getClassLoader() {

              return classLoader;

       }

 

       public void setClassLoader(ClassLoader classLoader) {

              this.classLoader = classLoader;

       }

 

}

 

 

2,无关的支持类

/**

 *

 */

package com.withub.gis.client.app.context;

 

import java.util.HashMap;

import java.util.Map;

 

import org.osgi.framework.BundleContext;

 

 

 

/**

 * @author 沈东良 Edward Shen [email protected]

 *

 */

public class GISApplicationContext {

 

       /**

        *

        */

       public GISApplicationContext() {

              // TODO Auto-generated constructor stub

       }

 

       /**

        * @param args

        */

       public static void main(String[] args) {

              // TODO Auto-generated method stub

 

       }

       private static GISApplicationContext instance=null;

       private static Object lockInstance=new Object();

    private String  username="";

    private String  password="";

    private String sessionId;

   

   

    private BundleContext  bundleContext;

    private ClassLoader classLoader;

 

    private Map<String,Object> map=new HashMap<String,Object>();

    /**

     *

     * @return

     */

    public static GISApplicationContext getInstance(){

         if(GISApplicationContext.instance==null){

                synchronized(GISApplicationContext.lockInstance){

                       if(GISApplicationContext.instance==null){

                              GISApplicationContext.instance=new GISApplicationContext();

                       }

                      

                }

               

         }

          return GISApplicationContext.instance;

    }

   public String getUsername() {

              return username;

       }

 

       public void setUsername(String username) {

              this.username = username;

       }

 

       public String getPassword() {

              return password;

       }

 

       public void setPassword(String password) {

              this.password = password;

       }

 

       public String getSessionId() {

              return sessionId;

       }

 

       public void setSessionId(String sessionId) {

              this.sessionId = sessionId;

       }

 

       public Map<String, Object> getMap() {

              return map;

       }

 

       public BundleContext getBundleContext() {

              return bundleContext;

       }

 

       public void setBundleContext(BundleContext bundleContext) {

              this.bundleContext = bundleContext;

       }

 

       public ClassLoader getClassLoader() {

              return classLoader;

       }

 

       public void setClassLoader(ClassLoader classLoader) {

              this.classLoader = classLoader;

       }

 

      

}

 

 

3IApplication的实现类,这是RCP程序的入口点。应该在其他Activator启动后执行。这里是Spring的消费者。

/**

 *

 */

package com.withub.gis.client.app.eclipse.application;

 

 

import java.awt.Rectangle;

import java.rmi.server.UID;

import java.util.Iterator;

import java.util.Set;

 

import javax.units.SI;

 

import net.refractions.udig.internal.ui.JaiErrorDialog;

import net.refractions.udig.internal.ui.UDIGWorkbenchAdvisor;

import net.refractions.udig.internal.ui.UiPlugin;

 

import org.eclipse.core.runtime.Platform;

import org.eclipse.equinox.app.IApplication;

import org.eclipse.equinox.app.IApplicationContext;

import org.eclipse.jface.dialogs.MessageDialog;

import org.eclipse.swt.widgets.Display;

import org.eclipse.ui.IWorkbench;

import org.eclipse.ui.PlatformUI;

import org.eclipse.ui.application.WorkbenchAdvisor;

import org.geotools.referencing.FactoryFinder;

import org.springframework.osgi.context.DelegatedExecutionOsgiBundleApplicationContext;

 

import com.withub.gis.client.app.context.GISApplicationContext;

import com.withub.gis.client.app.plugin.Activator;

import com.withub.gis.osgi.util.springSupport.StandAloneOsgiApplicationContextCreator;

import com.withub.gis.server.login.ILoginWSSecurity;

import com.withub.gis.ui.dialog.LoginDialog;

 

/**

 * @author 沈东良 Edward Shen [email protected]

 *

 */

public class GISApplication implements IApplication {

    private ILoginWSSecurity loginWSSecurity;

       public ILoginWSSecurity getLoginWSSecurity() {

              return loginWSSecurity;

       }

 

       public void setLoginWSSecurity(ILoginWSSecurity loginWSSecurity) {

              this.loginWSSecurity = loginWSSecurity;

       }

 

       /**

        *

        */

       public GISApplication() {

              // TODO Auto-generated constructor stub

       }

        

    protected WorkbenchAdvisor createWorkbenchAdvisor() {

           return new UDIGWorkbenchAdvisor();

          /*

        return new UDIGWorkbenchAdvisor() {

            @Override

            public String getInitialWindowPerspectiveId() {

                return "net.refractions.udig.tutorials.customapp.perspective";

            }

        };

        */

    }

   

   

    /**

     * Override to perform your own security check.

     *

     * @return true to indicate a successful login

     */

    public  boolean checkLogin() {

        LoginDialog loginDialog = new LoginDialog(

                "登陆WithubGIS系统",

                "请输入用户名和密码:" );

       

        boolean login= false;

      

        while( !login ){

             loginDialog.clearUserNamePassword();

            int result = loginDialog.open();                   

            if( result == MessageDialog.OK){

                try {

                   Activator activator=Activator.getDefault();

                   DelegatedExecutionOsgiBundleApplicationContext applicationContext=activator.getApplicationContext();

                  

                    ILoginWSSecurity loginWSSecurity=       (ILoginWSSecurity)applicationContext.getBean("loginWSSecurityOsgiReference");

                   //loginWSSecurity.login(loginDialog.getUser(), loginDialog.getPassword());

                   //login =loginService.checkLogin( loginDialog.getUser(), loginDialog.getPassword() );

                   String sessionId=loginWSSecurity.login(loginDialog.getUser(), loginDialog.getPassword());

                    GISApplicationContext.getInstance().setSessionId(sessionId);

                   login=true;

                                  

                } catch (Throwable connectionProblem) {

                   System.err.println(connectionProblem.getMessage());

                   MessageDialog.openError(null, "登录错误", "用户名或者密码错误,请重新登陆!");

                   // MessageDialog.openInformation(null, "不能连接服务器,请检查网络", connectionProblem.toString() );

                   

                   // return false; // probably should prompt user here?

                }

            }

            else {

                return false; // user cancelled

            }

        }

       // WithubGISApplicationContext.getInstance().getMap().put("loginService", loginService);

      

        return true;

    }

 

 

    /**

     * Starts GIS application with the given context and returns a result. This method must not exit

     * until the application is finished and is ready to exit. The content of the context is

     * unchecked and should conform to the expectations of the application being invoked.

     * <p>

     * Applications can return any object they like. If an <code>Integer</code> is returned it is

     * treated as the program exit code if Eclipse is exiting.

     * <p>

     * Note: This method is called by the platform; it is not intended to be called directly by

     * clients.

     * </p>

     *

     * @return the return value of the application

     * @see #EXIT_OK

     * @see #EXIT_RESTART

     * @see #EXIT_RELAUNCH

     * @param context the application context to pass to the application

     * @exception Exception if there is a problem running this application.

     */

 

    public Object start( IApplicationContext context ) throws Exception {

         

         

         

        WorkbenchAdvisor workbenchAdvisor = createWorkbenchAdvisor();

        Display display = PlatformUI.createDisplay();

 

        boolean isInitalized = init();

        if (!isInitalized) {

            return EXIT_OK;

        }

        int returnCode = EXIT_OK;

        try {

            returnCode = PlatformUI.createAndRunWorkbench(display, workbenchAdvisor);

        } catch (Throwable t) {

            UiPlugin.log("Messages.UDIGApplication_error", t);

        } finally {

            Platform.endSplash();

            display.dispose();

        }

        if (returnCode == PlatformUI.RETURN_RESTART) {

            return EXIT_RESTART;

        }

        return EXIT_OK;

    }

 

  

 

    /**

     * Forces this running application to exit. This method should wait until the running

     * application is ready to exit. The {@link #start(IApplicationContext)} should already have

     * exited or should exit very soon after this method exits

     * <p>

     * This method is only called to force an application to exit. This method will not be called if

     * an application exits normally from the {@link #start(IApplicationContext)} method.

     * <p>

     * Note: This method is called by the platform; it is not intended to be called directly by

     * clients.

     * </p>

     */

    public void stop() {

        final IWorkbench workbench = PlatformUI.getWorkbench();

        if (workbench == null){

            return;

        }

        final Display display = workbench.getDisplay();

        display.syncExec(new Runnable(){

            public void run() {

                if (!display.isDisposed()){

                    workbench.close();

                }

            }

        });

    };

 

    /**

     * Called before the workbench is created.

     * <p>

     * The following checks are performed:

     * <ul>

     * <li>checkForJAI(): optional - Dig will work with reduced functionality if JAI is not

     * available

     * <li>checkForGDI(): required - uDig will not function on WIN_32 if GDI is not present

     * </ul>

     * This method also loads some commonly used objects; subclasses may override this method (say

     * to ask the user to login)

     *

     * @return <code>true </code> on successful startup; false to exit the application with an

     *         error.

     */

    protected boolean init() {

        checkForJAI();

        boolean required = checkForGDI();

 

        if (!required) {

            // we could not meet our requirements; please exit!

            return false;

        }

 

        loadCommonlyUsedObject();

 

        boolean login = checkLogin();

        if (!login) {

            return false;

        }

        return true;

    }

 

    /**

     * Forces the class loader to load several troublesome classes; mostly focused on FactorySPI

     * plugins used by the GeoTools library.

     */

    private void loadCommonlyUsedObject() {

        // potential fix for win32 (occasionally blocks in Drawing.feature(Point/etc) during first

        // render)

        new UID(); // seed the random number generator

 

        load(FactoryFinder.getCoordinateOperationAuthorityFactories());

        load(FactoryFinder.getCoordinateOperationAuthorityFactories());

        load(FactoryFinder.getCRSFactories());

        load(FactoryFinder.getCSFactories());

        load(FactoryFinder.getDatumAuthorityFactories());

        load(FactoryFinder.getDatumFactories());

        load(FactoryFinder.getMathTransformFactories());

        @SuppressWarnings("unused")

        Object o = SI.BIT;

        o = SI.GRAM;

        o = SI.KILOGRAM;

        o = SI.METER;

        o = SI.RADIAN;

        o = SI.SECOND;

        o = SI.STERADIAN;

    }

 

    @SuppressWarnings("unchecked")

    private void load( Set coordinateOperationAuthorityFactories ) {

        for( Iterator iter = coordinateOperationAuthorityFactories.iterator(); iter.hasNext(); ) {

            iter.next();

        }

    }

 

    /**

     * Ensures that GDI is available for the windows inclined. GDI is used by SWT to perform matrix

     * operations; uDIG cannot function without GDI on windows.

     *

     * @return false if GDI is needed and not found.

     */

    public  boolean checkForGDI() {

        if (Platform.getOS().equals(Platform.OS_WIN32)) {

            // test to make sure that GDI+ is installed

              org.eclipse.swt.graphics.Image image = null;

              org.eclipse.swt.graphics.Path path = null;

            try {

                image = new  org.eclipse.swt.graphics.Image(Display.getCurrent(), 10, 10);

                path = net.refractions.udig.ui.graphics.SWTGraphics.convertToPath(new Rectangle(0, 0, 8, 8), Display.getCurrent());

            } catch (Exception e) {

                MessageDialog

                        .openError(

                                Display.getCurrent().getActiveShell(),

                                net.refractions.udig.ui.internal.Messages.UDIGApplication_title,

                                net.refractions.udig.ui.internal.Messages.UDIGApplication_error1

                                        + net.refractions.udig.ui.internal.Messages.UDIGApplication_error2

                                        + "http://www.microsoft.com/downloads/details.aspx?FamilyID=6A63AB9C-DF12-4D41-933C-BE590FEAA05A&displaylang=en"); //$NON-NLS-1$

                return false;

            } finally {

                if (image != null)

                    image.dispose();

                if (path != null)

                    path.dispose();

            }

        }

        return true;

    }

 

    /**

     * Ensures Java Advanced Imaging is installed into the JRE being used.

     * <p>

     * If JAI is not available a dialog will be displayed and false is returned. JAI is not required

     * for everything; currently rasters will not function without JAI; but many simple vector

     * formats will.

     * </p>

     *

     * @return true if JAI is available.

     */

    public  boolean checkForJAI() {

        try {

            Class.forName("javax.media.jai.operator.OrDescriptor"); //$NON-NLS-1$

            return true;

        } catch (Throwable th) {

            JaiErrorDialog.display();

            return false;

        }

    }

 

       /**

        * @param args

        */

       public static void main(String[] args) {

              // TODO Auto-generated method stub

 

       }

 

}

 

 

 

4Spring配置

<?xml version="1.0" encoding="UTF-8"?>

<beans xmlns="http://www.springframework.org/schema/beans"

    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

    xmlns:aop="http://www.springframework.org/schema/aop"

    xmlns:context="http://www.springframework.org/schema/context"

    xmlns:flow="http://www.springframework.org/schema/webflow-config"

    xmlns:jee="http://www.springframework.org/schema/jee"

    xmlns:jms="http://www.springframework.org/schema/jms"

    xmlns:lang="http://www.springframework.org/schema/lang"

    xmlns:osgi="http://www.springframework.org/schema/osgi"

    xmlns:osgi-compendium="http://www.springframework.org/schema/osgi-compendium"

    xmlns:p="http://www.springframework.org/schema/p"

    xmlns:tx="http://www.springframework.org/schema/tx"

    xmlns:util="http://www.springframework.org/schema/util"

    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd

       http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd

       http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd

       http://www.springframework.org/schema/webflow-config http://www.springframework.org/schema/webflow-config/spring-webflow-config-1.0.xsd

       http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee.xsd

       http://www.springframework.org/schema/jms http://www.springframework.org/schema/jms/spring-jms.xsd

       http://www.springframework.org/schema/lang http://www.springframework.org/schema/lang/spring-lang.xsd

       http://www.springframework.org/schema/osgi http://www.springframework.org/schema/osgi/spring-osgi.xsd

       http://www.springframework.org/schema/osgi-compendium http://www.springframework.org/schema/osgi-compendium/spring-osgi-compendium.xsd

       http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd

       http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd">

 

    <bean id="gISApplicationContext" class="com.withub.gis.client.app.context.GISApplicationContext"  factory-method="getInstance" >

 

  </bean>

  <bean id="bundleContext" factory-bean="gISApplicationContext"  factory-method="getBundleContext"></bean>

 

  <bean id="userBySessionServiceOsgiReference" factory-bean="userBySessionServiceOsgiReferenceFactory"  factory-method="getService">     

   </bean>

   <bean id="userBySessionServiceOsgiReferenceFactory" class="com.withub.gis.osgi.util.springSupport.importService.ImportOsgiServiceFactory">

    

      <property name="bundleContext">

         <ref  bean="bundleContext"/>

      </property>

      

      <property name="interfaces">

         <list>

            <value>com.withub.gis.server.login.IUserBySessionService</value>

         </list>     

      </property>

     

    

   </bean>

   

  

   <bean id="loginWSSecurityOsgiReference" factory-bean="loginWSSecurityOsgiReferenceFactory"  factory-method="getService">     

   </bean>

   <bean id="loginWSSecurityOsgiReferenceFactory" class="com.withub.gis.osgi.util.springSupport.importService.ImportOsgiServiceFactory">

      

      <property name="bundleContext">

          <ref  bean="bundleContext"/>

      </property>

      

      <property name="interfaces">

         <list>

            <value>com.withub.gis.server.login.ILoginWSSecurity</value>

         </list>     

      </property>

     

      <property name="retryTimes">

          <value>5</value>

      </property>

      <property name="waitTime">

         <value>1000</value>

      </property>

   </bean>

 

</beans>

 

 

代码说明

 

1,已内建bundleContext这个Bean

 

OsgiBundleXmlApplicationContext创建Application时,会创建一个Bean,名字叫bundleContext,类型是BundleContext

由于我们的方案中,内部和SpringDM一样都使用了OsgiBundleXmlApplicationContext,因此,我们的Spring内部也有bundleContext这个Bean

因此,Spring配置中

<bean id="gISApplicationContext" class="com.withub.gis.client.app.context.GISApplicationContext"  factory-method="getInstance" >

 

  </bean>

  <bean id="bundleContext" factory-bean="gISApplicationContext"  factory-method="getBundleContext"></bean>

   2Bean可以不用。

   Activator类的start()方法中

GISApplicationContext.getInstance().setBundleContext(context);

             

    这行代码也不需要。

 

 

2,外部对象插入Spring的技巧

 

这里介绍一个Spring的小技巧。

Spring对于静态类的静态工厂方法,这个类单例在外部也可以使用!是同一的。

这是很好的外部代码插入Spring管理的代码的途径!

 

我的代码中使用GISApplicationContext类的单例拿到BundleContext的实例,插进Spring中就是使用了这个技巧。

 

 

3,解决服务注册和导入先后次序的问题的独创方法

 

还有一个问题,B插件发布服务,A插件导入服务。就像我的例子那样,A插件依赖于B插件。

但是很有可能B插件发布服务的时间远远慢于A插件导入服务的时间。

这就会出现问题。特别是我这里的例子,A插件还是RCP程序的入口,IApplicaiton接口的实现类所在的插件。

这意味着A插件会很快启动,一般是比B插件先启动的。

 

可以设置OSGIStart Level,保证提供服务的插件先启动。

 

 

但我这里推荐的是一种自创的方法,仅在Eclipse下测试成功,不保证在所有OSGI环境下都能成功。

有使用其他OSGI环境经验的朋友可以帮忙测试一下这招是否有效。测好了,把结果告诉我好吗!谢谢!

 

 

首先,在提供OSGI服务的插件中发布一个Package

然后,在导入OSGI服务的插件的Activator类的start()方法中new一个提供服务插件的发布Package中的类。

然后再创建ApplicationContext

这可以保证在创建ApplicationContext之前,提供OSGI服务的插件已启动。

 

    另外,ImportOsgiServiceFactory类也提供了重试的机制,可以让用户配置重试的次数和每次间隔的时间,以保证OSGI服务的引用正确!

 

 

 

 

 

你可能感兴趣的:(OSGI服务发布和导入的自主实现—OSGI+Spring+Hibernate+...完美解决方案[非SpringDM]之二)