熱點推薦:
您现在的位置: 電腦知識網 >> 編程 >> Java編程 >> Java核心技術 >> 正文

加載遠程服務上的spring獨立子模塊

2022-06-13   來源: Java核心技術 

  背景

  假設一個web工程有個獨立業務子模塊userhomerpc個獨立子模塊也獨立發布子模塊獨立發布後可以及時reloadweb工程的業務功能個子模塊可以在任何服務器上也可以是個不同的公司來提供

  一般我們的工程會采用spring來管理bean在這種情況下要稍微改造下看上去和熱部署也有點類似

  這次的知識點以這個背景為例來進行講解

  首先看下這樣做的一些好處

  業務模塊的獨立按需加載可以加快web容器的啟動每次只需要啟動時加載自己需要的內容

  發布更新更快速獨立發布子模塊影響局部的業務功能

  原理

  我們先做一個子模塊userjar(在共享裡)

  userjar裡面就一個spring_userxml和Userjava

  

  spring_userxml

  <bean id=userclass=comwzucxdUser>

  <property name=namevalue=xxx />

  </bean>

  

  Userjava

  packagecomwzucxd;

  public class User {

  private Integer id;

  private String name;

  public Integer getId() {

  return id;

  }

  public void setId(Integer id) {

  thisid = id;

  }

  public String getName() {

  return name;

  }

  public void setName(String name) {

  thisname = name;

  }

  }

  下面就是模擬父容器加載子模塊的case

  基本思路通過XmlBeanFactory先加載子模塊的bean對象的BeanDefinition然後將BeanDefinition注冊到父容易的beanFactory最後對加載bean的AppClassloader改造成需要的ClassLoader(這裡改造成URLClassLoader)

  詳細代碼以及示例如下

  public class Test {

  public static void main(String[] args) {

  try {

  //讀取spring全局配置文件(這裡是一個空內容的文件沒有任何內容)即我們平時web project父容器上下文

  //當然平時這裡會用ClassPathXmlApplicationContext看文件所在位置了…

  ApplicationContextapplicationContext = newFileSystemXmlApplicationContext(file://\\share\\ebook\\jse\\classloader\\spring_configxml

  //創建全局spring BeanFactory目的是將所有子模塊的bean對象注冊到這個父容器上下文中

  DefaultListableBeanFactorybeanFactory = (DefaultListableBeanFactory)applicationContextgetAutowireCapableBeanFactory()

  //獨立模塊的spring bean配置文件位置

  String configurationFilePath = jar:file://\\share\\ebook\\jse\\classloader/userjar!/spring_userxml;

  //這裡可以做一個邏輯如果該配置文件不存在那麼父容器啟動的時候這個子模塊就不加載

  URL url = new URL(configurationFilePath)

  //建立遠程資源訪問

  UrlResource urlResource = new UrlResource(url)

  XmlBeanFactory xmlBeanFactory = new XmlBeanFactory(urlResource)

  String[] beanIds =xmlBeanFactorygetBeanDefinitionNames()

  for (String beanId : beanIds) {

  //獲得的子模塊bean對象

  BeanDefinition bd =xmlBeanFactorygetMergedBeanDefinition(beanId)

  //在這裡將子模塊bean對象注冊到父容易上下文中完成bean對象的Definition

  beanFactoryregisterBeanDefinition(beanId bd)

  }

  //接著要進行classloader的改變加載的class文件現在不在classpath下而是其他地方(遠程共享http服務或者其他協議服務的機器上)

  //這時候就需要將父容易中beanFactory的加載bean的classloader改變(父容易中beanFactory默認是AppClassLoader這種情況下改成用URLClassLoader)

  // 以下這行設置BeanFactory的ClassLoader為URLClassLoader以加載外部類

  setBeanClassLoader(beanFactory)

  //以下是測試是否注入成功

  //從父容器上下文中獲取user對象

  Object pluginBean =applicationContextgetBean(user

  //測試結果

  String val = tryInvoke(pluginBean)

  Systemoutprintln(val)

  } catch (Exception exc) {

  excprintStackTrace()

  }

  }

  private static void setBeanClassLoader(

  DefaultListableBeanFactorybeanFactory)

  throws MalformedURLException {

  //指明spring_userxml配置出現的bean對象所在jar位置

  String jarFilePath = file://\\share\\ebook\\jse\\classloader\\userjar;

  URL jarUrl = new URL(jarFilePath)

  URL[] urls = new URL[] { jarUrl };

  URLClassLoader cl = new URLClassLoader(urls)

  beanFactorysetBeanClassLoader(cl)

  }

  private static String tryInvoke(Object bean) throws SecurityException

  NoSuchMethodExceptionIllegalArgumentException

  IllegalAccessExceptionInvocationTargetException {

  Class<?> paramTypes[] = new Class[];

  Method method =beangetClass()getDeclaredMethod(getName paramTypes)

  Object paramValues[] = new Object[];

  Object obj = methodinvoke(bean paramValues)

  //……

  return (String)obj;

  }

  }

  這裡如果我們不改變BeanClassLoader會有什麼問題呢?會出現classnofound異常這個主要原因就是默認的beanfactory classloader是AppClassLoader

  當然還有另外一種方式將jar中的類掃描出來自己創建個classloader一個個添加進去這種方式更加靈活多變其實還是使用spring的bean管理方式使用比較方便已經解決了主要場景

  public static void main(String[] args) throws Exception {

  URL url = new URL(jar:file:d:\\userjar!/

  URLClassLoader uc = new URLClassLoader(new URL[]{url})

  Class<?> cls = ucloadClass(comwzucxdUser

  Object obj = clsnewInstance()

  Systemoutprintln(obj)

  }


From:http://tw.wingwit.com/Article/program/Java/hx/201311/27186.html
  • 上一篇文章:

  • 下一篇文章:
  • 推薦文章
    Copyright © 2005-2022 電腦知識網 Computer Knowledge   All rights reserved.