OSGI动态注册和创建服务

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>


你可能感兴趣的:(OSGI动态注册和创建服务)