path的META-INF/services目录下的任何文件:
<import resource="classpath*:META-INF/services/*.ctx.xml" />
这种现成的功能正是当构建轻量级插件框架时你要利用的一个特色。
注意,Spring并不关心它自己的代码自动发现功能。这通常不是一个问题,因为大多数J2EE容器都提供一个lib目录,存放于这个目录下的任何jar文件将被自动地添加到classpath中。这意味着,如果你想以jar文件形式捐献你的代码的话,那么在任何一种J2EE容器中实现自发现都会是相当容易的事情。
在一个应用程序服务器外,使用例如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创建对
|