- 摘要:實現思路利用Spring中BeanFactoryPostProcessor的機制,在Spring載入完配置檔案完成Bean定義之後,通過讀取zk中配置內容,覆蓋BeanDefiniton中的propertyvalues實現過程配置相關注解定義@Config註解用於說明該類為配置類用於儲存相關配置資訊@Target({ElementType.TYPE})@Retention(RetentionPolicy.RUNTIME)@Documentedpublic@interfaceC
- 實現思路
實現過程利用Spring中BeanFactoryPostProcessor的機制,在Spring載入完配置檔案完成Bean 定義之後,通過讀取zk中配置內容,覆蓋Bean Definiton中的property values
配置相關注解定義@Config 註解用於說明該類為配置類用於儲存相關配置資訊
@Target({ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) @Documented public @interface Config { } 複製程式碼
@ConfigField 註解用於標註類的屬性欄位對應配置中的配置項
自定義BeanFactoryPostProcessor, 此處實現了介面beanDefinitionRegistryPostProcessor@Target({ElementType.FIELD}) @Retention(RetentionPolicy.RUNTIME) @Documented public @interface ConfigField { String key(); } 複製程式碼
該類主要用於實現方法 postProcessBeanDefinitionRegistry;其核心程式碼如下
// 獲取spring解析後的Bean 定義資訊 for (String beanName : beanDefinitionRegistry.getBeanDefinitionNames()) { BeanDefinition beanDefinition = beanDefinitionRegistry.getBeanDefinition(beanName); String className = beanDefinition.getBeanClassName(); Class<?> clazz = Class.forName(className); // 判斷該類是否為配置類 if (isConfigBean(clazz)) { // path 為 zk中應用對應節點 /config/app/env String configPath = path + "/" + className; Stat stat = curatorFramework.checkExists().forPath(configPath); if (stat != null) { String value = new String(curatorFramework.getData().forPath(configPath)); JSONObject jsonObject = JSONObject.parseObject(value); // 獲取配置類中欄位與配置項key的對應 Map configFieldMap = findConfigFieldAnnation(clazz); for (String key : jsonObject.keySet()) { String propertyValue = jsonObject.getString(key); String property = configFieldMap.get(key); // 採用zk中的值覆蓋到 Bean Definiton propertyValue beanDefinition.getPropertyValues().add(property, propertyValue); } log.info("Hxlzp config register bean : {}, property values : {}", className, value); } } } 複製程式碼
判斷類是否為配置類
private boolean isConfigBean(Class<?> clazz) { return clazz.getAnnotation(Config.class) != null; } 複製程式碼
獲取配置類的屬性與配置項的對應關係
zk 節點定義private Map findConfigFieldAnnation(Class<?> clazz) { Map map = new HashMap (); for (Field field : clazz.getDeclaredFields()) { ConfigField configField = field.getAnnotation(ConfigField.class); if (configField != null) { map.put(configField.key(), field.getName()); } } return map; }複製程式碼
如下圖所示:二級為應用節點, 三級為應用的所屬環境節點,四級為應用的各個環境下的配置節點,配置節點約束節點名必須與配置類的類名保持一致
zk 配置節點的資料格式配置節點資料採用json格式;如下
{
"db.username" : "",
"db.password" : "",
"db.url" : ""
}
使用示例
定義DB配置類定義類 DbConfig, 用於記錄Db相關配置
定義DataSource@Data @Config @Component("dbConfig") public class DbConfig { @ConfigField(key = "db.url") private String url; @ConfigField(key = "db.username") private String username; @ConfigField(key = "db.password") private String password; } 複製程式碼
此處採用 Druid作為資料來源
Spring 配置@Slf4j @Data public class ExampleDatasource extends DruidDataSource { @Resource private DbConfig dbConfig; /** * 重寫init;實現db配置後初始化 */ public void init () throws SQLException { if (!this.dbConfig.getUrl().equals(this.getUrl()) || !this.dbConfig.getUsername().equals(this.getUsername()) || !this.dbConfig.getPassword().equals(this.getPassword())) { // 說明首次初始化 或 db配置發生變化 此處也即實現了在無需重啟的情況下完成db資料來源的動態切換 this.inited = false; } if (inited) { // 因 getConnection 的時候 再次呼叫了init 需判斷是否已初始化過 return; } if (dbConfig != null) { log.info("datasource set db config , {}", dbConfig.getUrl()); this.setUrl(dbConfig.getUrl()); this.setUsername(dbConfig.getUsername()); this.setPassword(dbConfig.getPassword()); super.init(); } } } 複製程式碼
配置檔案中需定義 上文中 BeanDefinitionRegistryPostProcessor; 示例如下
init-method="init" destroy-method="close">
測試可以通過從ApplicationContext 中獲取dao執行簡單的操作驗證; 也可以修改zk中節點配置資料 驗證資料來源的動態切換
ClassPathXmlApplicationContext classPathXmlApplicationContext = new ClassPathXmlApplicationContext("applicationContext.xml"); classPathXmlApplicationContext.start(); classPathXmlApplicationContext.getBean(UserDao.class).getById(1); 複製程式碼
以上是採用spring zookeeper 實現簡單的配置管理的內容,更多 Zookeeper 採用 配置 簡單 實現 spring 管理 的內容,請您使用右上方搜尋功能獲取相關資訊。
採用spring zookeeper 實現簡單的配置管理
相關文章
- AI介面實現:簡單實現Viper配置管理AI
- 基於zookeeper實現統一配置管理
- ZooKeeper學習筆記三:使用ZooKeeper實現一個簡單的配置中心筆記
- ZooKeeper學習筆記四:使用ZooKeeper實現一個簡單的分散式鎖筆記分散式
- 簡易版的Spring框架之IOC簡單實現Spring框架
- Spring Boot實際專案用簡單的AOPSpring Boot
- PHP 實現簡單的資料採集併入庫PHP
- zookeeper簡單命令
- spring aop實現簡單的許可權控制功能Spring
- 用trait實現簡單的依賴注入AI依賴注入
- 用go實現簡單的氣泡排序Go排序
- Android應用加固的簡單實現方案Android
- 用 go 實現一個簡單的 mvcGoMVC
- 簡易版的Spring框架之AOP簡單實現(對我來說不簡單啊)Spring框架
- Java用UDP實現簡單聊天JavaUDP
- React 實現一個簡單實用的 Form 元件ReactORM元件
- Android應用加固的簡單實現方案(二)Android
- 自己用 Netty 實現一個簡單的 RPCNettyRPC
- 用canvas實現一個簡單的畫板Canvas
- 用 Rust 實現簡單的光線追蹤Rust
- 用ListView簡單實現滑動列表View
- 用natapp簡單實現內網穿透APP內網穿透
- AOP的簡單實現
- 簡單的 HashMap 實現HashMap
- 實現簡單的BitMap
- ArrayList的簡單實現
- SAP MM 採購申請審批的一個簡單實現方式
- 基於ZooKeeper,Spring設計實現的引數系統Spring
- Spring Cloud Gateway 實現簡單自定義過濾器SpringCloudGateway過濾器
- 用JS實現簡單的螢幕錄影機JS
- 用java實現一個簡單的區塊鏈Java區塊鏈
- 用python實現簡單的線上翻譯程式Python
- 應用內路徑規劃的簡單實現
- 用java實現一個簡單的計算器Java
- Spring Boot 之路(一):一個簡單的Spring Boot應用Spring Boot
- 用 JavaScript 實現簡單拼圖遊戲JavaScript遊戲
- Vue+Electron實現簡單桌面應用Vue
- 用 Swift 實現一個簡單版 ReactSwiftReact