• 使用NetBeans6开发OSGi应用(2)——SecondOSGi[88250原创]


    转载请保留作者信息:

    作者:88250

    Bloghttp:/blog.csdn.net/DL88250

    MSN & Gmail & QQDL88250@gmail.com


    摘要

    上一次,我们了解了OSGi的背景并使用NetBeans6,基于Knopflerfish(OSGi的一个RI) 完成了第一个OSGi应用——FirstOSGi。这一次,我们将对OSGi进行深入一点学习——SecondOSGi,让我们掌握Bundles之间的调用!

    准备

    上一次 :-)

    开工:

    1. 创建工程

    打开NetBeans6 IDE,创建两个普通的Java App——SecondOSGi、SecondOSGiClient。把KF下的Sources拷贝到两个工程下(记得加入asm3.0的Jar):

            

    在SecondOSGiClient工程的demo包下的两个Java文件(Demo.java, DemoFactory.java)与SecondOSGi工程demo包下的完全一样,这里是懒得发布编译好的class byte file给Client了,直接给的接口源文件。

    2. 编写manifest.mf

    把工程View切换到Files,改写manifest.mf如下:





    关于manifest.mf里各种properties就不罗嗦了,有很多文档可以参考 :-)

    3. 编写Activator

    下面逐一给出源文件,一一对应上面工程结构图。

    service提供者,即SecondOSGi工程下的:

    /*
     * @(#)Demo.java
     * 
     * This program is free software; you can redistribute it and/or modify
     * it under the terms of the GNU General Public License as published by
     * the Free Software Foundation; either version 3 of the License, or
     * (at your option) any later version.
     * 
     * This program is distributed in the hope that it will be useful,
     * but WITHOUT ANY WARRANTY; without even the implied warranty of
     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     * GNU Library General Public License for more details.
     * 
     * You should have received a copy of the GNU General Public License
     * along with this program; if not, write to the Free Software
     * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
     
    */
    package secondosgi.service.demo;


    /**
     * A simple demo service.
     * 
    @author 88250
     * 
    @version 1.0.0.0, Feb 14, 2008
     
    */
    public interface Demo {

        
    /**
         * Add two integers and return the result.
         * 
    @param a
         * 
    @param b
         * 
    @return 
         
    */
        
    public int add(int a, int b);
    }

    /*
     * @(#)DemoFactory.java
     * 
     * This program is free software; you can redistribute it and/or modify
     * it under the terms of the GNU General Public License as published by
     * the Free Software Foundation; either version 3 of the License, or
     * (at your option) any later version.
     * 
     * This program is distributed in the hope that it will be useful,
     * but WITHOUT ANY WARRANTY; without even the implied warranty of
     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     * GNU Library General Public License for more details.
     * 
     * You should have received a copy of the GNU General Public License
     * along with this program; if not, write to the Free Software
     * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
     
    */
    package secondosgi.service.demo;

    /**
     * <b>Another</b> very simple demo service API.
     * <p>
     * The intentions of this interface class is to show that different bundles
     * will get different instances of a service, by the means of a 
     * ServiceFactory.
     * </p>
     * 
    @author 88250
     * 
    @version 1.0.0.0, Feb 14, 2008
     
    */
    public interface DemoFactory {

        
    /**
         * Say hello.
         
    */
        
    void hello();
    }

    /*
     * @(#)DemoImpl.java
     * 
     * This program is free software; you can redistribute it and/or modify
     * it under the terms of the GNU General Public License as published by
     * the Free Software Foundation; either version 3 of the License, or
     * (at your option) any later version.
     * 
     * This program is distributed in the hope that it will be useful,
     * but WITHOUT ANY WARRANTY; without even the implied warranty of
     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     * GNU Library General Public License for more details.
     * 
     * You should have received a copy of the GNU General Public License
     * along with this program; if not, write to the Free Software
     * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
     
    */
    package secondosgi.service.demo.impl;

    import secondosgi.service.demo.Demo;

    /**
     * Implementation of the Demo service.
     * 
    @author 88250
     * 
    @version 1.0.0.0, Feb 14, 2008
     
    */
    public class DemoImpl implements Demo {

        
    public int add(int a, int b) {
            
    return a + b;
        }
    }

    /*
     * @(#)DemoFactoryImpl.java
     * 
     * This program is free software; you can redistribute it and/or modify
     * it under the terms of the GNU General Public License as published by
     * the Free Software Foundation; either version 3 of the License, or
     * (at your option) any later version.
     * 
     * This program is distributed in the hope that it will be useful,
     * but WITHOUT ANY WARRANTY; without even the implied warranty of
     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     * GNU Library General Public License for more details.
     * 
     * You should have received a copy of the GNU General Public License
     * along with this program; if not, write to the Free Software
     * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
     
    */
    package secondosgi.service.demo.impl;

    import secondosgi.service.demo.DemoFactory;
    import org.osgi.framework.Bundle;

    /**
     * Implementation of the DemoFactory service. The intentions of this
     * class is to show that different bundles will get different instances
     * of a service, by the means of a ServiceFactory.
     * 
    @author 88250
     * 
    @version 1.0.0.0, Feb 14, 2008
     
    */
    public class DemoFactoryImpl implements DemoFactory {

        
    private Bundle b;

        
    /**
         * Constructor with argument.
         * 
    @param b a <code>Bundle</code> 
         
    */
        
    public DemoFactoryImpl(Bundle b) {
            
    this.b = b;
        }

        
    public void hello() {
            System.out.println(
    "Hello bundle #" + b.getBundleId());
        }
    }

    很关键的Activator,实现服务的注册,注销:
    /*
     * @(#)Activator.java
     * 
     * This program is free software; you can redistribute it and/or modify
     * it under the terms of the GNU General Public License as published by
     * the Free Software Foundation; either version 3 of the License, or
     * (at your option) any later version.
     * 
     * This program is distributed in the hope that it will be useful,
     * but WITHOUT ANY WARRANTY; without even the implied warranty of
     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     * GNU Library General Public License for more details.
     * 
     * You should have received a copy of the GNU General Public License
     * along with this program; if not, write to the Free Software
     * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
     
    */
    package secondosgi.service.demo.impl;

    import secondosgi.service.demo.Demo;
    import secondosgi.service.demo.DemoFactory;
    import java.util.Hashtable;
    import org.osgi.framework.Bundle;
    import org.osgi.framework.BundleActivator;
    import org.osgi.framework.BundleContext;
    import org.osgi.framework.ServiceFactory;
    import org.osgi.framework.ServiceRegistration;

    /**
     * Activator which creates and registers a Demo1 service.
     * 
    @author 88250
     * 
    @version 1.0.0.0, Feb 14, 2008
     
    */
    public class Activator implements BundleActivator {

        
    private Demo demo;

        
    public void start(BundleContext bc) {
            System.out.println(
    "start " + getClass().getName());
            demo 
    = new DemoImpl();
            bc.registerService(Demo.
    class.getName(),
                    demo,
                    
    new Hashtable());

            
    // Create a service factory for DemoFactory implementations
            ServiceFactory factory = new ServiceFactory() {

                Hashtable services 
    = new Hashtable();
                
    // Will get called when a bundle request a service
                @SuppressWarnings("unchecked")
                
    public Object getService(Bundle b,
                        ServiceRegistration reg) {
                    System.out.println(
    "get from " + b.getBundleId());

                    
    // Create when necessary
                    DemoFactory impl = (DemoFactory) services.get(b);
                    
    if (impl == null) {
                        impl 
    = new DemoFactoryImpl(b);
                        services.put(b, impl);
                    }
                    
    return impl;
                }

                
    // will get called when a bundle ungets a service or stops
                public void ungetService(Bundle b,
                        ServiceRegistration reg,
                        Object service) {
                    System.out.println(
    "unget from " + b.getBundleId());
                    services.remove(b);
                }
            };

            
    // Note how factory only implements ServiceFactory, 
            
    // but we still register as DemoFactory1 service
            bc.registerService(DemoFactory.class.getName(),
                    factory,
                    
    new Hashtable());
        }

        
    public void stop(BundleContext bc) {
            System.out.println(
    "stop " + getClass().getName());

            demo 
    = null;
        }
    }

    client角色,服务使用者,即SecondOSGiClient工程下的(Demo,DemoFactory两个接口同服务提供的)。
    在这个Activator里,我们实现了服务的查找、调用、服务提供者状态的监听:
    /*
     * @(#)Activator.java
     * 
     * This program is free software; you can redistribute it and/or modify
     * it under the terms of the GNU General Public License as published by
     * the Free Software Foundation; either version 3 of the License, or
     * (at your option) any later version.
     * 
     * This program is distributed in the hope that it will be useful,
     * but WITHOUT ANY WARRANTY; without even the implied warranty of
     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     * GNU Library General Public License for more details.
     * 
     * You should have received a copy of the GNU General Public License
     * along with this program; if not, write to the Free Software
     * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
     
    */
    package secondosgi.service.client.impl;

    import secondosgi.service.demo.Demo;
    import secondosgi.service.demo.DemoFactory;
    import org.osgi.framework.BundleActivator;
    import org.osgi.framework.BundleContext;
    import org.osgi.framework.ServiceEvent;
    import org.osgi.framework.ServiceListener;
    import org.osgi.framework.ServiceReference;

    /**
     * Activator which registers a listener for, and test, any Demo service.
     * 
    @author 88250
     * 
    @version 1.0.0.0, Feb 14, 2008
     
    */
    public class Activator implements BundleActivator, ServiceListener {

        
    private static BundleContext bc;

        
    private ServiceListener listener;

        
    public void start(BundleContext bc) {
            System.out.println(
    "start " + getClass().getName());
            Activator.bc 
    = bc;

            
    try {
                
    // Filter that matches all Demo services
                String filter = "(objectclass=" + Demo.class.getName() + ")";

                
    // Fetch all registered Demo services
                
    // and test them manually
                ServiceReference[] srl =
                        bc.getServiceReferences(Demo.
    class.getName(), filter);
                
    for (int i = 0; srl != null && i < srl.length; i++) {
                    testService(srl[i]);
                }

                
    // ...and catch all newly registed ones too.
                bc.addServiceListener(listener, filter);
            } 
    catch (Exception e) {
                
    // sounds unlikely, but filter syntax errors are easy to write.
                e.printStackTrace();
            }

            testServiceFactory();
        }

        
    void testServiceFactory() {
            
    // Try to get a reference to the service produced by a factory
            ServiceReference factorySR = bc.getServiceReference(DemoFactory.class.getName());
            
    if (factorySR != null) {
                DemoFactory df 
    = (DemoFactory) bc.getService(factorySR);
                
    if (df != null) {
                    
    // Different bundles will get different printouts
                    df.hello();
                }
            }
        }

        
    void testService(ServiceReference sr) {
            Demo demo 
    = (Demo) bc.getService(sr);
            
    int r = demo.add(1401);

            System.out.println(
    "Testing " + demo + ", result=" + r);

            
    // ..return the object to be nice
            bc.ungetService(sr);
        }

        
    public void stop(BundleContext bc) {
            System.out.println(
    "stop " + getClass().getName());
            Activator.bc 
    = null;
        }

        
    public void serviceChanged(ServiceEvent event) {
            ServiceReference sr 
    = event.getServiceReference();

            
    // just print some info and call testService() on
            
    // all registered Demo services
            switch (event.getType()) {
                
    case ServiceEvent.REGISTERED:
                    System.out.println(
    "Got Demo service");
                    testService(sr);
                    
    break;
                
    case ServiceEvent.UNREGISTERING:
                    System.out.println(
    "Lost Demo service");
                    
    break;
                
    case ServiceEvent.MODIFIED:
                    System.out.println(
    "Modified Demo service");
                    
    break;
                
    default:
                    
    break;
            }
        }
    }

    4. 测试

    打开KF控制中心:

    daniel@daniel-laptop:~/Work/knopflerfish_osgi_2.0.4/knopflerfish.org/osgi$ java -jar framework.jar 


    打开构建好的SecondOSGi.jar以及SecondOSGiClient.jar,运行!



    总结

    这一次,我们对OSGi的了解更深了一步。

    从设计的角度:一个可扩展的Service-Oriented组件服务模型

    从开发的角度:我们发布接口给客户,实现了“针对接口编程”的OO核心实践

    不足之处

    我们一直都是在KF的控制台下启动的应用,如何做成独立的(standalone)可运行的Jar发布呢?

    1. 在命令行下启动OSGi框架

    首先,编写一个启动参数文件:secondosgi.xargs
    -launch
    -istart /home/daniel/Work/Sources/Java/SecondOSGi/dist/SecondOSGi.jar
    -istart /home/daniel/Work/Sources/Java/SecondOSGiClient/dist/SecondOSGiClient.jar

    然后,进入KF的安装目录,启动我们的应用:


    现在,我们只是脱离了KF的图形界面控制中心,在命令行下面启动的KF框架,并把SecondOSGi与SeondOSGiClient安装运行在KF框架里。一切的主动权还是在KF手里。
    结合以前JavaEE的实践,JSP/Servlets,EJBs不都是被控制在容器(container)里的吗?
    不过,话又说回来了,我希望自己的框架应用构建于OSGi之上,而不是之内。
    之内的部分应该是可扩展的Plug-ins部分,让OSGi作为底层框架,为我们提供稳定的插件机制。
    之外的部分应该是我们应用的框架,构建在OSGi之上。对OSGi做一个封装,就KF而言,就是封装它的命令接口,让我们的框架可以对插件随时安装、卸载、运行、停止、更新。。。。
    当然,以上是个设想,学习OSGi第二天的设想。。。。
    总之不足的地方很多,要把这个示例慢慢演化成正真具有价值的应用可能还需要一些时间。

  • 相关阅读:
    [编写高质量代码:改善java程序的151个建议]建议72 生成字列表后不要再操作原列表
    [编写高质量代码:改善java程序的151个建议]建议71 推荐使用subList处理局部列表
    [编写高质量代码:改善java程序的151个建议]建议70 子列表只是原列表的一个视图
    程序员的简历到底该怎么写?(转)
    SQL数据库数据优化SQL优化总结( 百万级数据库优化方案)
    sqlserver的四种分页方式
    sql server中截取字符串的常用函数(自己经常到用的时候想不起来所以拿到这里)
    SQL之存储过程详细介绍及语法(篇幅比较长慢慢看)
    超经典SQL练习题,做完这些你的SQL就过关了
    SqlServer 数据库引擎优化顾问优化数据库(消耗内存很大)
  • 原文地址:https://www.cnblogs.com/lanzhi/p/6470598.html
Copyright © 2020-2023  润新知