知识大全 加载远程服务上的spring独立子模块

Posted

篇首语:知是行的主意,行是知的功夫。本文由小常识网(cha138.com)小编为大家整理,主要介绍了知识大全 加载远程服务上的spring独立子模块相关的知识,希望对你有一定的参考价值。

  背景

  假设一个web工程有 个独立业务子模块 user home rpc 个独立子模块也独立发布 子模块独立发布后可以及时reloadweb工程的业务功能 个子模块可以在任何服务器上 也可以是 个不同的公司来提供

  一般我们的工程会采用spring来管理bean 在这种情况下要稍微改造下 看上去和热部署也有点类似

  这次的知识点以这个背景为例来进行讲解

  首先看下这样做的一些好处

   业务模块的独立按需加载 可以加快web容器的启动 每次只需要启动时加载自己需要的内容

   发布更新更快速 独立发布子模块影响局部的业务功能

  原理

   我们先做一个子模块user jar(在 共享里)

  user jar里面就一个spring_user xml和User java

  

  spring_user xml

  <bean id= user class= wzucxd User >

  <property name= name value= xxx />

  </bean>

  

  User java

  package wzucxd;

  public class User

  private Integer id;

  private String name;

  public Integer getId()

  return id;

  

  public void setId(Integer id)

  this id = id;

  

  public String getName()

  return name;

  

  public void setName(String name)

  this name = 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\\\\j se\\\\classloader\\\\spring_config xml )

  //创建全局spring BeanFactory 目的是将所有子模块的bean对象注册到这个父容器上下文中

  DefaultListableBeanFactorybeanFactory = (DefaultListableBeanFactory)applicationContext getAutowireCapableBeanFactory()

  //独立模块的spring bean配置文件位置

  String configurationFilePath = jar:file:// \\\\share\\\\ebook\\\\j se\\\\classloader/user jar!/spring_user xml ;

  //这里可以做一个逻辑 如果该配置文件不存在 那么父容器启动的时候这个子模块就不加载

  URL url = new URL(configurationFilePath)

  //建立远程资源访问

  UrlResource urlResource = new UrlResource(url)

  XmlBeanFactory xmlBeanFactory = new XmlBeanFactory(urlResource)

  String[] beanIds =xmlBeanFactory getBeanDefinitionNames()

  for (String beanId : beanIds)

  //获得的子模块bean对象

  BeanDefinition bd =xmlBeanFactory getMergedBeanDefinition(beanId)

  //在这里将子模块bean对象注册到父容易上下文中 完成bean对象的Definition

  beanFactory registerBeanDefinition(beanId bd)

  

  //接着要进行classloader的改变 加载的class文件现在不在classpath下 而是其他地方(远程共享 服务或者其他协议服务的机器上)

  //这时候就需要将父容易中beanFactory的加载bean的classloader改变(父容易中beanFactory默认是AppClassLoader 这种情况下改成用URLClassLoader)

  // 以下这行设置BeanFactory的ClassLoader为URLClassLoader 以加载外部类

  setBeanClassLoader(beanFactory)

  //以下是测试是否注入成功

  //从父容器上下文中获取user对象

  Object pluginBean =applicationContext getBean( user )

  //测试结果

  String val = tryInvoke(pluginBean)

  System out println(val)

   catch (Exception exc)

  exc printStackTrace()

  

  

  private static void setBeanClassLoader(

  DefaultListableBeanFactorybeanFactory)

  throws MalformedURLException

  //指明spring_user xml配置出现的bean对象所在jar位置

  String jarFilePath = file:// \\\\share\\\\ebook\\\\j se\\\\classloader\\\\user jar ;

  URL jarUrl = new URL(jarFilePath)

  URL[] urls = new URL[] jarUrl ;

  URLClassLoader cl = new URLClassLoader(urls)

  beanFactory setBeanClassLoader(cl)

  

  private static String tryInvoke(Object bean) throws SecurityException

  NoSuchMethodException IllegalArgumentException

  IllegalAccessException InvocationTargetException

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

  Method method =bean getClass() getDeclaredMethod( getName paramTypes)

  Object paramValues[] = new Object[ ];

  Object obj = method invoke(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:\\\\user jar!/ )

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

  Class<?> cls = uc loadClass( wzucxd User )

  Object obj = cls newInstance()

  System out println(obj)

cha138/Article/program/Java/hx/201311/27186

相关参考

知识大全 win7带网络的安全模式无法连接网络,提示无法加载远程访问连接管理器服务,错误711

win7带网络的安全模式无法连接网络,提示无法加载远程访问连接管理器服务,错误711从微软官网上找到的推荐解决方案如果禁用了下列服务,可能会发生此问题:电话服务远程访问连接管理器远程访问自动连接管理器

知识大全 使用分布式缓存来群集Spring远程服务

使用分布式缓存来群集Spring远程服务  以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!lishix

知识大全 电脑连不上网 开机的时候变得非常卡,网络连接显示无法加载远程访问连接管理器服务 求解答

电脑连不上网开机的时候变得非常卡,网络连接显示无法加载远程访问连接管理器服务求解答一、可以通过电脑管家网络修复功能修复一下。1.打开电脑管家,点击工具箱。2.找到网络修复工具3.点击“立即修复”即可。

知识大全 Linux下独立添加PHP扩展模块

Linux下独立添加PHP扩展模块  以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!  服务器运行一段

知识大全 使用数据模块和远程数据模块

 使用数据模块和远程数据模块    数据模块是包含了非可视化组件的特殊的窗体这些组件可以与那些可视化控件一起在普通的窗体中使用不过如果用户计划重新使用

知识大全 Spring动态加载Hibernate映射文件

Spring动态加载Hibernate映射文件  以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!&nb

知识大全 TUX 2.0使用手册--六、用户区的可加载模块

TUX2.0使用手册--六、用户区的可加载模块  以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!  为

知识大全 加载远程图片时,经常因为缓存而得不到更新的解决方法

  原理很简单让你每次获取远程图片的url不同即可复制代码代码如下:cha138/Article/program/Java/JSP/201311/19852

知识大全 请慎用spring-ClassPathXmlApplicationContext手动加载sprin

请慎用spring-ClassPathXmlApplicationContext手动加载sprin  以下文字资料是由(全榜网网www.cha138.com)小编为大家搜

知识大全 什么是模块,模块和应用程序的区别,模块的好处

什么是模块,模块和应用程序的区别,模块的好处系统只有一个内核,内核模块在模块加载时,将执行代码加载到内核中,开始执行、生效运行空间不同普通应用程序是用户态,在用户空间执行,内核模块在系统内核空间执行。