OSGi 系列(十三)之 Configuration Admin Service
OSGi 的 CM 就是 Configuration Admin Service,是用于管理 Bundle 属性、并在属性发生变更时通知相应的 Service,这是保持 OSGi 动态性的很关键的一个服务。
1. ConfigurationAdmin
用于管理配置数据的服务,主要有两个作用:
- 获取配置数据
- 更新配置数据
public class ConfigurationAdminDemo {
private ConfigurationAdmin configurationAdmin;
public void init() {
try {
Configuration conf = configurationAdmin.getConfiguration("jdbc.mysql");
Dictionary<String, Object> dict = conf.getProperties();
System.out.println(dict);
Dictionary<String, String> properties = new Hashtable<>();
properties.put("username", "root");
properties.put("password", "123456");
conf.update(properties);
} catch (IOException e) {
e.printStackTrace();
}
}
public ConfigurationAdmin getConfigurationAdmin() {
return configurationAdmin;
}
public void setConfigurationAdmin(ConfigurationAdmin configurationAdmin) {
this.configurationAdmin = configurationAdmin;
}
}
blueprint.xml 配制文件:
<reference id="configurationAdmin" interface="org.osgi.service.cm.ConfigurationAdmin" />
<bean class="com.edu.osgi.cm.ConfigurationAdminDemo" init-method="init">
<property name="configurationAdmin" ref="configurationAdmin" />
</bean>
结果如下:
2. ManagedService
用来关联和操作单个配置文件的服务当相关联的配置文件发生变化的时候,会通知到相应的服务。
public class DBConfigManagedService implements ManagedService {
public void updated(Dictionary<String, ?> properties) throws ConfigurationException {
System.out.println("======updated======");
System.out.println(properties);
}
}
blueprint.xml 配制文件:
<service interface="org.osgi.service.cm.ManagedService">
<service-properties>
<entry key="service.pid" value="jdbc.mysql" />
</service-properties>
<bean class="com.edu.osgi.cm.DBConfigManagedService" />
</service>
手动修改 jdbc.mysql.cfg 文件后,结果如下:
3. blueprint 中 cm 的使用
<?xml version="1.0" encoding="UTF-8"?>
<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:cm="http://aries.apache.org/blueprint/xmlns/blueprint-cm/v1.1.0"
xsi:schemaLocation="http://www.osgi.org/xmlns/blueprint/v1.0.0 http://www.osgi.org/xmlns/blueprint/v1.0.0/blueprint.xsd
http://aries.apache.org/blueprint/xmlns/blueprint-cm/v1.1.0 http://aries.apache.org/schemas/blueprint-cm/blueprint-cm-1.1.0.xsd">
<cm:property-placeholder persistent-id="jdbc.mysql.conf" update-strategy="reload"/>
<bean class="com.edu.osgi.cm.MysqlConfig" init-method="display">
<property name="className" value="${className}" />
<property name="url" value="${url}" />
<property name="username" value="${username}" />
<property name="password" value="${password}" />
</bean>
</blueprint>
4. karaf 中 cm 命令
-
config:list "(service.pid=jdbc.mysql)"
列出 jdbc.mysql 配制文件 -
config:edit
编辑属性config:edit jdbc.mysql config:property-set name join config:update
5. ManagedServiceFactory
用来关联和操作多个配置文件的服务,当多个相关联的配置文件发生变化的时候,都会通知到相应的服务。
(1) 环境准备
<dependency>
<groupId>org.osgi</groupId>
<artifactId>org.osgi.core</artifactId>
<version>5.0.0</version>
</dependency>
<dependency>
<groupId>org.osgi</groupId>
<artifactId>org.osgi.compendium</artifactId>
<version>5.0.0</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-dbcp2</artifactId>
<version>2.1.1</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.38</version>
</dependency>
(2) 实现 ManagedServiceFactory 接口
public class DataSourceServiceFactory implements ManagedServiceFactory {
private BundleContext bundleContext;
private Map<String, ServiceRegistration<?>> serviceMap = new ConcurrentHashMap<>();
public String getName() {
return "DataSourceServiceFactory";
}
// 更新配置文件
public void updated(String pid, Dictionary<String, ?> properties) throws ConfigurationException {
System.out.println("============updated============");
System.out.println(pid);
System.out.println(properties);
BasicDataSource bds = new BasicDataSource();
bds.setDriverClassName(properties.get("driverClassName").toString());
bds.setUrl(properties.get("url").toString());
bds.setUsername(properties.get("username").toString());
bds.setPassword(properties.get("password").toString());
Dictionary<String, String> props = new Hashtable<>();
props.put("instance", properties.get("instance").toString());
ServiceRegistration<?> sr = bundleContext.registerService(DataSource.class.getName(), bds, props);
System.out.println("------------");
serviceMap.put(pid, sr);
}
// 删除配置文件
public void deleted(String pid) {
System.out.println("============deleted============");
System.out.println(pid);
ServiceRegistration<?> sr = serviceMap.get(pid);
sr.unregister();
serviceMap.remove(pid);
}
public void setBundleContext(BundleContext bundleContext) {
this.bundleContext = bundleContext;
}
}
(3) blueprint.xml
<?xml version="1.0" encoding="UTF-8"?>
<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:cm="http://aries.apache.org/blueprint/xmlns/blueprint-cm/v1.1.0"
xsi:schemaLocation="http://www.osgi.org/xmlns/blueprint/v1.0.0 http://www.osgi.org/xmlns/blueprint/v1.0.0/blueprint.xsd
http://aries.apache.org/blueprint/xmlns/blueprint-cm/v1.1.0 http://aries.apache.org/schemas/blueprint-cm/blueprint-cm-1.1.0.xsd">
<service interface="org.osgi.service.cm.ManagedServiceFactory">
<service-properties>
<entry key="service.pid" value="jdbc.datasource"/>
</service-properties>
<bean class="com.edu.osgi.cm.DataSourceServiceFactory">
<property name="bundleContext" ref="blueprintBundleContext" />
</bean>
</service>
<!--<reference interface="javax.sql.DataSource" filter="(instance=test)"/>-->
</blueprint>
(4) 测试
# 安装事务
feature:install transaction
install -s mvn:org.apache.commons/commons-pool2/2.4.2
install -s mvn:org.apache.commons/commons-dbcp2/2.1.1
install -s mvn:mysql/mysql-connector-java/5.1.18
在 deploy 目录下新建二个文件 jdbc.datasource-dev.cfg、jdbc.datasource-test.cfg(注意:文件要以 jdbc.datasource 开头,"-" 分隔)
jdbc.datasource-dev.cfg
instance=dev
driverClassName=com.mysql.jdbc.Driver
url=jdbc:mysql:///dev
username=root
password=root
jdbc.datasource-test.cfg
instance=test
driverClassName=com.mysql.jdbc.Driver
url=jdbc:mysql:///test
username=root
password=root