知识大全 基于Eclipse开发轻量级Spring插件
Posted 知
篇首语:锲而舍之,朽木不折;锲而不舍,金石可镂。本文由小常识网(cha138.com)小编为大家整理,主要介绍了知识大全 基于Eclipse开发轻量级Spring插件相关的知识,希望对你有一定的参考价值。
基于Eclipse开发轻量级Spring插件 以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!
摘要 本文介绍如何在Eclipse中利用Spring框架作为一个平台来创建轻量级的能够与你的现有J EE应用程序无缝集成的插件
一 引言
一般地 企业软件产品都要求在客户端具有定制能力 而且当客户必须修改核心产品的配置来引入他们自己的定制时一般都要求进行更新操作 借助于易于扩展和可升级的高度模块化的软件 插件技术能够提供针对这种典型场所下的完美解决方案
注释 什么是插件呢?一个插件是使用什么样的代码构成的?
在众多的定义当中 我认为最好的定义当属Eclipse工程中所定义的 插件是一种代码贡献 它能够把代码添加到一个系统中的众所周知的扩展点处 也就是说 一个插件是一个良好定义的代码包(例如一个jar文件或目录) 它提供足够的配置能力来实现在系统中的一个特定的众所周知的位置插入和激活自身
插件本身还可以定义另外的其它插件能够扩展的扩展点 一个扩展点定义了一个语言接口(该插件将提供它的一个实现)和使用该被发现的插件的组件 一个扩展点能够接受被动态地发现和在运行时刻配置的插件
借助于一种拥有清晰定义的扩展点的插件环境 核心产品可以自由升级 而且插件本身可以根据独立的计划发行和升级 例如 借助于我的开源Classpath助理工程(基于Eclipse的插件框架) 我可以按常规来升级我的Eclipse 而且还可以轻松地发行我自己的插件的更新版本
特别对于Java开发者来说 与现有J EE组件(参考 注释 J EE组件不是插件吗? )相比 插件提供了一种更好的升级技术 可以设想你的许多EJB是由不同的开发小组构建的 然后 在了解它们能够良好工作的情况下 就可以把它们整合到一个应用程序中 一个插件架构应该是允许进行这种级别的组件化的
注释 J EE组件不是插件吗?
是的 J EE组件 例如EJB和Servlet 都不是插件 尽管它们都具有一定程度的 可插入性 (这是指 你能够交换一个EJB或Servlet实现) 但是配置它们并不那么清晰明快 而且它们缺乏一个插件所具有的容易的升级能力 例如 Servlet无法把代码与配置结合到一起 因此 尽管你能够在其自己的jar文件中打包一个servlet实现 但是 此时你往往需要修改web xml以便servlet容器能够识别它
乍看上去 EJB似乎更象插件 它们包含提供有关自己信息的发布描述符 然而 EJB也不是插件 因为 典型情况下 它们都要求外部配置(一种在EAR的application xml中的引用) 并且 典型地 它们在其各自的发布描述符中进行彼此参考 这两种特征都使一个EJB无法成为 插件式可发布的
借助于流行的Spring框架的BeanFactoryPostProcessor接口 开发者可以轻松地创建一个轻量级插件框架 本文正是想讨论如何实现这一点 同时 还要向你展示一个使用轻量级插件的工作示例
二 准备你的插件平台
在你的平台能够支持可插入的组件前 它需要满足下列两个标准
· 组件必须是自发现的 你已经了解到J EE组件不能成为真正插件的准确理由 典型情况下 你应该找到一个需要升级的外部配置文件以便该平台能够感知新的代码
· 组件必须包含足够信息以便在应用程序内部集成或配置其本身
如果你仅是添加一些不需要与系统进行协作的代码(也就是说 松耦合的) 那么自动发现就是很简单的 真正的挑战是结合有紧密集成的自发现
三 Spring中的自发现功能
事实证明 Spring实际上为支持插件开发作了比较好的准备 Spring已经能够在若干种bean上下文文件中存储配置 并且它使得自发现配置文件非常简单 例如 下面的Spring语句自动发现以ctx xml结尾的存在于classpath的META INF/services目录下的任何文件
<import resource= classpath*:META INF/services/* ctx xml />
这种现成的功能正是当构建轻量级插件框架时你要利用的一个特色
注意 Spring并不关心它自己的代码自动发现功能 这通常不是一个问题 因为大多数J EE容器都提供一个lib目录 存放于这个目录下的任何jar文件将被自动地添加到classpath中 这意味着 如果你想以jar文件形式捐献你的代码的话 那么在任何一种J EE容器中实现自发现都会是相当容易的事情
在一个应用程序服务器外 使用例如ant这样的工具来实现jar文件的自发现也是非常容易的 下列的Apache Ant XML以一种与一个应用程序服务器类似的方式检测所有的存在于lib目录下的jar文件
<path id= classpath ><fileset dir= $basedir/lib ><include name= **/* jar /></fileset></path> <target name= start server description= launches the server process ><java classname= platform bootstrap Server ><classpath refid= classpath /></java></target>
因此 尽管Spring并不直接支持自发现功能 但是通过使用标准技术 你仍然可以使你的代码容易地实现自发现 这一点 与Spring的能够自动检测配置的能力相结合 就可以使你既能够实现代码捐献的目的也能够使你的代码在系统中被发现和激活
四 在Spring中实现自配置
你需要进一步实现的是 使插件具有自配置能力 尽管Spring并不直接支持这种功能 但是 借助于它提供的一些工具 实现这一目标也是相当直接的 实现自配置的关键部分是BeanFactoryPostProcessor 这是一个Spring调用的接口(该调用应该是在所有配置被发现和加载到一个内存描述之后 但在创建实际的对象之前发生)
通过使用BeanFactoryPostProcessor 你可以动态地把所有的bean组合到一起而不必修改原始的文件系统配置 下列代码是我的BeanFactoryPostProcessor实现的核心部分 PluginBeanFactoryPostProcessor(下载源码中提供了完整的类)
private String extensionBeanName;//经由spring设置(在此没有显示setter)private String propertyName;//经由spring设置(在此没有显示setter)private String pluginBeanName;//经由spring设置(在此没有显示setter)/**(非Javadoc)*@请参考BeanFactoryPostProcessor#postProcessBeanFactory(ConfigurableListableBeanFactory)*/public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory)throws BeansException //找到我们希望修改的bean定义BeanDefinition beanDef = beanFactory getBeanDefinition(extensionBeanName);
//在该bean定义中 查找它的属性并且发现我们将修改的具体属性 MutablePropertyValues propValues = beanDef getPropertyValues();if ( !propValues contains(propertyName))throw new IllegalArgumentException( Cannot find property + propertyName + in bean + extensionBeanName);PropertyValue pv = propValues getPropertyValue(propertyName);
//取出值定义(在我们的情况下 我们仅支持列表风格属性的更新)Object prop = pv getValue();if ( !(prop instanceof List))throw new IllegalArgumentException( Property + propertyName + in extension bean + extensionBeanName + is not an instanceof List ); //把我们的bean参考添加到列表中 当Spring创建对象// 并且把它们绑定到一起时 我们的bean现在准备好了 List l = (List) pv getValue();l add(new RuntimeBeanReference(pluginBeanName));
下面展示了配置在Spring中看上去的样子 首先 在你的核心工程中定义扩展点 它是example craps Table的一个实例 其中它的两个属性(dice players)配置以空列表 这是标准的Spring用法
<beans><bean id= extension point craps table class= example craps Table init method= init ><property name= dice ><list></list></property><property name= players ><list></list></property></bean></beans>
现在 你可以使用插件类连同它的Spring上下文(这将是自发现的)打包一个jar文件 并且你可以拥有一个类似如下的配置
<beans><bean id= real dice class= example craps RealDice /><bean class= platform spring PluginBeanFactoryPostProcessor ><property name= extensionBeanName value= extension point craps table /><property name= propertyName value= dice /><property name= pluginBeanName value= real dice /></bean></beans>
在这个Spring配置中定义了一个example craps RealDice的实例 然后 它定义你的PluginBeanFactoryPostProcessor(它被配置以找到extension point craps table bean) 这一实例还会把你的real dice bean添加到craps表的dice属性中
注意 这是本文中真正的焦点所在 这个到Spring的小扩展就是编写基于插件的组件的所有要求 注意 如果你删除这个包含该Spring上下文的jar文件 那么 你还要从extension point craps table bean中 分离 你的bean 然后 把该jar添加回去 并且把它自己绑定到系统中的适当位置
五 使用轻量级插件进行开发
我常常吃惊于大多数的架构师团队极少地考虑开发者能否容易地使用他们的框架 其实 EJB就是一种具有学术式优点的极好的例子 但是 其实践中的开发缺点使其变得极为昂贵 所以 我认为 当选用一种框架实现典型的编码/构建/调试工作时 先了解一下该框架具有什么样的负荷能力和影响是非常重要的
从这种角度来看 轻量级插件则是相当 无痛苦 的 你可以把每一个插件作为它自己的简单地依赖于核心产品的jar的可构建工程 这在一种类似于Eclipse这样的工具(在其中 核心产品具有其自己的Java工程并且每一种插件也都有其自己的)中是很容易建模的 你仅需要一个最终的装配工程 它依赖于核心产品和包括的各种插件工程 通过使装配工程依附于核心和插件工程 你的classpath会被自动地正确构建 本文的下载源码中提供了一个类似这样的工程 记住 你可以为每一种客户创建一个装配工程 从而允许你把不同的插件与不同的客户相匹配 这种方式与Eclipse恰好吻合 允许在调试期间的增长式编译和代码热交换 这使你的开发进程相当灵活 不必要加入完全妨碍Eclipse的本机Java支持的构建步骤
六 一切都是插件吗?
Eclipse的一个根本特征是 一切都是插件(请参考注释 Eclipse插件比较) 从系统的初始启动到Java开发环境 再到在线帮助系统 每一种捐献代码(即使不是Java代码的代码)都以一种插件形式存在 这种方式具有其优点 但是它规定了一种工业插件开发环境 具有完整的工具 例如管理组件 调试器支持 等等 幸好 Eclipse提供了这些功能 但是 具有这种级别支持的服务器端框架并不存在(据我所知)
注释 Eclipse插件比较
比较于Eclipse插件 我一直把该插件称作是轻量级的 但是你可能疑惑 凭什么说它们是轻量级的?其实 我使用术语 轻量级 术语主要是强调 实现一种基于插件的架构的主要优点是相当轻快和简单的
Eclipse工程基于一种具有工业强度的插件架构 因此 我认为 把稍微扩展Spring框架功能的插件架构与一种具有丰富特征的插件实现进行比较是很有价值的
多个类加载器支持
Eclipse工程具有一种复杂的类加载模型 这区别于(但非完全不同于)一种应用程序服务器的使用类加载器层次的方式 既然Eclipse鼓励第三方进行插件开发 那么很可能存在具体类的命名和版本冲突问题
通过不支持同一个类的多个版本 轻量级方法则可以完全避免这个问题 例如 对于我所工作的应用程序来说 这就是一种合理的约束 因为我们主要使用插件来提供一种可信的升级功能 我们只是或多或少控制我们想使用哪些版本和jar文件 因此 我们不需要多个类加载器支持
Manifest和其它Meta信息
Eclipse插件提供了一种详细的manifest 它负责不仅提供有关一个插件扩展了哪些扩展点的信息而且还提供有关它如何依赖于其它插件的信息 在运行时刻 你可以浏览该插件仓库以发现插件并且遍历它们的依赖性 Eclipse鼓励使用一种 懒惰式 插件加载模型 当实现一个扩展点时 你必须显式地查找扩展它的那个插件 并且 典型地 你仅加载你需要的那些插件 这种方案减少了启动时间并且能够防止因加载不用的对象而造成资源浪费
Meta信息也是很重要的 Eclipse可以使用它来强制实现你的声明 Eclipse能够通知你有关丢失的相关性信息 告诉你使用相同的扩展点时何时你有太多或太少的插件 等等
借助于轻量级插件 你不必拥有一个正常的manifest 它允许你以编程方式存取你依赖的内容 而且所有的你的插件在运行时刻加载 只是你必须自己来进行任何类型的检查
如果不使用一种显式的依赖性列表 那么 你必须或者把所有你对于第三方的依赖性打包到你的插件jar中或者假定一种第三方类的基本集合总是位于客户环境中 如果你忘记一些东西 那么你就会遇到典型的挑战 确定丢失了哪些jar文件
在实践中 我经常需要决定是否要构建第三方库(如果它是顾客特定的jar 那么 典型情况下 我都把它们嵌入到这个插件jar中 如果我使用一种标准的开源包 例如Jakarta mons 那么我会经常把它添加到核心应用程序中) 当轻量级过于 轻量级 并且你不能以一种ad hoc方式来管理这些类型的依赖性时 作好调用判断确实更为重要
至于其它的manifest相关数据 你可以通过提供一种轻量级的manifest来扩展PluginBeanFactoryPostProcessor java以便跟踪具有插件的bean 你还可以使用该信息来强制实施一些约束规则
在服务器端开发中 构建的EJB JSP/Servlet等组件并不是以真正插件的形式出现的 它们都要求真正的工作以便定义和归档一个扩展点 因此 把一切都当作一个插件可能会增加大量工作 因为大多数J EE工程师可能对此不太熟悉
我总是试图把插件作为一种工具来实现特定领域的定制目的 同样地 利用Spring创建轻量级的与你的现有应用程序和技术无缝接合的插件就成为极其紧迫的任务 注意 在大部分情况下 你的应用程序通常是一种比较独立的Spring/J EE应用程序
cha138/Article/program/Java/ky/201311/28956相关参考
Eclipse经典开发教程插件安装 以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧! Eclipse
知识大全 Eclipse入门之使用指南及开发Eclipse插件 (2)
Eclipse入门之使用指南及开发Eclipse插件(2) 以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一
关于Eclipse插件开发之定制向导(图) 以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧! Inv
Eclipse3.0简介和插件开发示例 以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧! Eclip
开发一个调试JSP的Eclipse插件 以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧! JAVA调
Eclipse插件开发中的Java项目模型 以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧! Jav
Eclipse插件开发中实现刷新和重编译介绍 以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧! 在做
基于Spring框架的WebSphere应用开发 以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!
基于OSGi和Spring开发Web应用 以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧! 作为一个
知识大全 轻量级IoC容器来扩展ANT享受SPRING(图)
轻量级IoC容器来扩展ANT享受SPRING(图) 以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!