OSGI动态注册和创建服务

来源:互联网 发布:c语言中的char=a[] 编辑:程序博客网 时间:2024/05/16 15:52

1、需要引入

<dependency>            <groupId>org.osgi</groupId>            <artifactId>org.osgi</artifactId>            <version>3.0.0</version>        </dependency>

2、创建一个工厂类实现接口ManagedServiceFactory

public class WserviceFactory implements ManagedServiceFactory {    private static final Logger log = LoggerFactory.getLogger(WserviceFactory.class);    private BundleContext context;    private APIServices apiServices;    private String[] interfaces;    public BundleContext getContext() {        return context;    }    public void setContext(BundleContext context) {        this.context = context;    }    /**     * 服务:key为appid     */    private final Map<String, ServiceRegistration> existingServices = new HashMap<>();    /**     * pid与appid的映射关系     */    private final Map<String, String> PidNameMap = new HashMap<>();    public WserviceFactory() {        Class<?>[] allinterfaces = WwService.class.getInterfaces();        List<String> ifacelist = new ArrayList<>();        for (Class<?> iface : allinterfaces) {            ifacelist.add(iface.getName());        }        interfaces = (String[]) ifacelist.toArray(new String[ifacelist.size()]);    }    @Override    public String getName() {        return "JMust_Service";    }    @Override    public void updated(String pid, Dictionary dctnr) throws ConfigurationException {        log.info("JMust_Service update: pid=" + pid);        if (dctnr == null) {            log.warn("文件:" + pid + "为空,无法创建服务");            return;        }        String WwServiceName;        String WwSecret = null;        String WwAppID = dctnr.get("AppID").toString();        // 服务名不能空        if (WwAppID == null) {            log.warn(pid + "文件中AppID参数没有配置或者为空,无法创建服务!");            return;        } else {            WwSecret = dctnr.get("Secret").toString();            if (WxAppID.trim().isEmpty()) {                log.warn(pid + "文件中AppID参数没有配置或者为空,无法创建服务!");                return;            }            // 服务名不能重复            if (existingServices.containsKey(WwAppID)) {                if (WwAppID.equals(PidNameMap.get(pid))) {                    // 同一配置文件修改的情况                    log.info("更新已有的服务实例\"" + WwAppID + "\"");                    ServiceRegistration ppcService;                    ppcService = existingServices.get(WwAppID);                    if (ppcService != null) {                        log.info("Unregister WwService Instance:" + WwAppID);                        ppcService.unregister();                    } else {                        log.warn("No WwService Instance:" + WwAppID);                    }                    existingServices.remove(WwAppID);                } else {                    // 不同配置文件的服务实例名冲突                    log.error("服务实例名\"" + WwAppID + "\"和其他配置文件里的服务实例名冲突,保留原有服务实例。");                    return;                }            }            // 先清除当前配置文件原来对应的服务资源            String LegacyServiceName = PidNameMap.get(pid);            if (LegacyServiceName != null) {                ServiceRegistration ppcService = existingServices.get(LegacyServiceName);                if (ppcService != null) {                    ppcService.unregister();                }                existingServices.remove(LegacyServiceName);                PidNameMap.remove(pid);            }        }        // 设置服务相关属性        ServiceRegistration ppcService;        Dictionary props = new Hashtable();        props.put("instance", WxAppID);        // 设置WwService相关属性        WxService instance = new WxService(WwAppID, WwSecret);        instance.setApiServices(apiServices);        if (instance == null) {            log.error("[" + pid + "]配置参数格式有误!创建WwService失败!");            return;        }        ppcService = context.registerService(interfaces, instance, props);        existingServices.put(WwAppID, ppcService);        PidNameMap.put(pid, WwAppID);    }    @Override    public void deleted(String pid) {        ServiceRegistration ppcService;        String ServiceName = PidNameMap.get(pid);        if (ServiceName != null) {            ppcService = existingServices.get(ServiceName);            if (ppcService != null) {                ppcService.unregister();            }            existingServices.remove(ServiceName);            PidNameMap.remove(pid);        }    }    public boolean isExistAppId(String appId) {        if (existingServices.containsKey(appId)) {            return true;        }        return false;    }    public void setApiServices(APIServices apiServices) {        this.apiServices = apiServices;        for (String key : existingServices.keySet()) {            WwService service = (WwService) context.getService(existingServices.get(key).getReference());            if (service != null) {                service.setApiServices(this.apiServices);            }        }    }}

3、将相关属性初始化到需要用到的地方

public class WwService implements IWwService {    private String AppID;    private String Secret;    private APIServices apiServices;    public WxService(String appid, String secret) {        this.AppID = appid;        this.Secret = secret;    }    public void setApiServices(APIServices apiServices) {        this.apiServices = apiServices;    }    public APIServices getApiServices() {        return apiServices;    }}

4、假如说,我们需要初始化的时候创建很多的服务,那么我们可以通过将所有的服务接口注入到一个接口服务类,看blueprint的配置,如:

<reference id="aService" interface="com.jmust.test.iface.IAAPI"        availability="optional" />    <reference id="bService" interface="com.jmust.test.iface.IBAPI"        availability="optional" />    <reference id="cService" interface="com.jmust.test.iface.ICAPI"        availability="optional" />    <reference id="dService" interface="com.jmust.test.iface.IDAPI"        availability="optional" />    <reference id="eService" interface="com.jmust.test.iface.IEAPI"        availability="optional" />    <reference id="fService" interface="com.jmust.test.iface.IFAPI"        availability="optional" />    <reference id="gService" interface="com.jmust.test.iface.IGAPI"        availability="optional" />    <reference id="hService" interface="com.jmust.test.iface.IHAPI"        availability="optional" />    <reference id="iService" interface="com.jmust.test.iface.IIAPI"        availability="optional" />    <reference id="jService"        interface="com.jmust.test.iface.IJAPI"        availability="optional" />    <reference id="kService" interface="com.jmust.test.iface.IKAPI"        availability="optional" />    <bean id="APIServicesBean" class="com.jmust.test.pwservice.Factory.APIServices">        <property name="aService" ref="aService" />        <property name="bService" ref="bService" />        <property name="cService" ref="cService" />        <property name="dService" ref="dService" />        <property name="eService" ref="eService" />        <property name="fService" ref="fService" />        <property name="gService" ref="gService" />        <property name="hService" ref="hService" />        <property name="iService" ref="iService" />        <property name="jService" ref="jService" />        <property name="kService" ref="kService" />    </bean>

5、将上面这些接口通过一个服务发布出去,这样子就相当于一次性发布了所有需要不发布的服务了

<!--服务配置后自动发布 -->    <bean id="WServiceFactory" class="com.jmust.test.pwservice.Factory.WserviceFactory">        <property name="context" ref="blueprintBundleContext" />        <property name="apiServices" ref="APIServicesBean" />    </bean>    <service id="WServiceFactoryService" ref="WServiceFactory"        interface="org.osgi.service.cm.ManagedServiceFactory">        <service-properties>            <entry key="service.pid" value="JMust_Service" />        </service-properties>    </service>

6、到此,将服务发布出去后,每当我们增加一个新的cfg文件,就会创建一份新的服务,从而达到了横向扩展了。

创建一个JMust_Service_0001.cfg文件,里面的内容是:

AppID=123456789
Secret=abcdefg

保存后,把他扔到servicemix的etc里面既可马上创建对应于这个cfg中的APPID为123456789的服务了;

假如说,我再创建一封新的cfg文件,就上面的APPID不一样外,保存,发布到etc下面,那么也会出马上创建一份服务

7、服务创建好之后,我们就需要应用这些服务了,那么该怎么办呢?

创建个实现类:
public class ServiceRegister{    private BundleContext bundleContext;    private static final Logger LOG = LoggerFactory.getLogger(ServiceRegister.class);    public static final ConcurrentHashMap<String, IWwService> serviceMap = new ConcurrentHashMap<>();    public synchronized void register(ServiceReference<IWwService> reference) throws Exception {        String appId = (String) reference.getProperty("instance");        IWwService service = bundleContext.getService(reference);        serviceMap.put(appId, service);        LOG.info("服务注册...." + reference.getBundle().getSymbolicName() + " AppID = " + appId);    }    public synchronized void unRegister(ServiceReference<IWwService> reference) throws Exception {        if (reference == null || reference.getProperty("instance") == null) {            return;        }        String appId = (String) reference.getProperty("instance");        if (serviceMap.containsKey(appId)) {            serviceMap.remove(appId);        }        LOG.info("服务卸载...." + reference.getBundle().getSymbolicName() + " AppID = " + appId);    }    public void setBundleContext(BundleContext bundleContext) {        this.bundleContext = bundleContext;    }}


blueprint中监听服务

 <!--获取服务列表-->    <bean id="serviceRegister" class="com.jmust.test.service.ServiceRegister">        <property name="bundleContext" ref="blueprintBundleContext" />    </bean>    <reference-list  availability="optional" interface="com.jmust.dest.pwservice.Iface.IWwService">        <reference-listener ref="serviceRegister" bind-method="register" unbind-method="unRegister" />    </reference-list>


0 0