首页 技术 正文
技术 2022年11月15日
0 收藏 512 点赞 4,360 浏览 5250 个字

一个公共工程中的Spring配置文件,可能会被多个工程引用。因为每个工程可能只需要公共工程中的一部分Bean,所以这些工程的Spring容器启动时,需要区分开哪些Bean要创建出来。另一种场景是:想通过Properties文件中的配置开关,就将Spring配置文件中Bean的实现切换成另一套。

方法一:Qulifier区分Bean

1.1应用实例

以Apache开源框架Jetspeed中的一段配置为例:page-manager.xml

===============================================================================

  <bean name="xmlPageManager"class="org.apache.jetspeed.page.psml.CastorXmlPageManager"init-method="init" destroy-method="destroy">
<meta key="j2:cat" value="xmlPageManager orpageSerializer" />
<constructor-arg index="0">
<ref bean="IdGenerator"/>
</constructor-arg>
<constructor-arg index="1">
<refbean="xmlDocumentHandlerFactory" />
</constructor-arg>
……
</bean> <bean id="dbPageManager"class="org.apache.jetspeed.page.impl.DatabasePageManager"init-method="init" destroy-method="destroy">
<meta key="j2:cat" value="dbPageManager orpageSerializer" />
<!-- OJB configuration file resourcepath -->
<constructor-arg index="0">
<value>JETSPEED-INF/ojb/page-manager-repository.xml</value>
</constructor-arg>
<!-- fragment id generator -->
<constructor-arg index="1">
<ref bean="IdGenerator"/>
</constructor-arg>
……
</bean>

1.2 Bean过滤器

JetspeedBeanDefinitionFilter在Spring容器解析每个Bean定义时,会取出上面Bean配置中j2:cat对应的值,例如dbPageManageror pageSerializer。然后将这部分作为正则表达式与当前的Key(从配置文件中读出)进行匹配。只有匹配上的Bean,才会被Spring容器创建出来。

JetspeedBeanDefinitionFilter

===============================================================================

    public boolean match(BeanDefinition bd)
{
String beanCategoriesExpression = (String)bd.getAttribute(CATEGORY_META_KEY);
boolean matched = true;
if (beanCategoriesExpression != null)
{
matched = ((matcher != null)&& matcher.match(beanCategoriesExpression));
}
return matched;
} public void registerDynamicAlias(BeanDefinitionRegistry registry, String beanName,BeanDefinition bd)
{
String aliases =(String)bd.getAttribute(ALIAS_META_KEY);
if (aliases != null)
{
StringTokenizer st = newStringTokenizer(aliases, " ,");
while (st.hasMoreTokens())
{
String alias = st.nextToken();
if (!alias.equals(beanName))
{
registry.registerAlias(beanName, alias);
}
}
}
}

===============================================================================

match()方法中的CATEGORY_META_KEY的值就是j2:cat,matcher类中保存的就是当前的Key,并负责将当前Key与每个Bean的进行正则表达式匹配。

registerDynamicAlias的作用是:在Bean匹配成功后,定制的Spring容器会调用此方法为Bean注册别名。详见下面1.3中的源码。

1.3定制Spring容器

定制一个Spring容器,重写registerBeanDefinition()方法,在Spring注册Bean时进行拦截。

===============================================================================

public class FilteringXmlWebApplicationContextextends XmlWebApplicationContext
{
private JetspeedBeanDefinitionFilterfilter; publicFilteringXmlWebApplicationContext(JetspeedBeanDefinitionFilter filter, String[]configLocations, Properties initProperties, ServletContext servletContext)
{
this(filter, configLocations,initProperties, servletContext, null);
} publicFilteringXmlWebApplicationContext(JetspeedBeanDefinitionFilter filter, String[]configLocations, Properties initProperties, ServletContext servletContext,ApplicationContext parent)
{
super();
if (parent != null)
{
this.setParent(parent);
}
if (initProperties != null)
{
PropertyPlaceholderConfigurer ppc =new PropertyPlaceholderConfigurer();
ppc.setIgnoreUnresolvablePlaceholders(true);
ppc.setSystemPropertiesMode(PropertyPlaceholderConfigurer.SYSTEM_PROPERTIES_MODE_FALLBACK);
ppc.setProperties(initProperties);
addBeanFactoryPostProcessor(ppc);
}
setConfigLocations(configLocations);
setServletContext(servletContext);
this.filter = filter;
} protected DefaultListableBeanFactorycreateBeanFactory()
{
return new FilteringListableBeanFactory(filter,getInternalParentBeanFactory());
}
}public classFilteringListableBeanFactory extends DefaultListableBeanFactory
{
private JetspeedBeanDefinitionFilterfilter; public FilteringListableBeanFactory(JetspeedBeanDefinitionFilterfilter, BeanFactory parentBeanFactory)
{
super(parentBeanFactory);
this.filter = filter;
if (this.filter == null)
{
this.filter = newJetspeedBeanDefinitionFilter();
}
this.filter.init();
} /**
* Override of the registerBeanDefinitionmethod to optionally filter out a BeanDefinition and
* if requested dynamically register anbean alias
*/
public void registerBeanDefinition(StringbeanName, BeanDefinition bd)
throws BeanDefinitionStoreException
{
if (filter.match(bd))
{
super.registerBeanDefinition(beanName, bd);
if (filter != null)
{
filter.registerDynamicAlias(this, beanName, bd);
}
}
}
}

1.4为Bean起别名

使用BeanReferenceFactoryBean工厂Bean,将上面配置的两个Bean(xmlPageManager和dbPageManager)包装起来。将Key配成各自的,实现通过配置当前Key来切换两种实现。别名都配成一个,这样引用他们的Bean就直接引用这个别名就行了。例如下面的PageLayoutComponent。

page-manager.xml

===============================================================================

<bean class="org.springframework.beans.factory.config.BeanReferenceFactoryBean">
<meta key="j2:cat"value="xmlPageManager" />
<meta key="j2:alias"value="org.apache.jetspeed.page.PageManager" />
<propertyname="targetBeanName" value="xmlPageManager" />
</bean> <bean class="org.springframework.beans.factory.config.BeanReferenceFactoryBean">
<meta key="j2:cat"value="dbPageManager" />
<meta key="j2:alias"value="org.apache.jetspeed.page.PageManager" />
<propertyname="targetBeanName" value="dbPageManager" />
</bean> <bean id="org.apache.jetspeed.layout.PageLayoutComponent"
class="org.apache.jetspeed.layout.impl.PageLayoutComponentImpl">
<meta key="j2:cat"value="default" />
<constructor-arg index="0">
<refbean="org.apache.jetspeed.page.PageManager" />
</constructor-arg>
<constructor-arg index="1">
<value>jetspeed-layouts::VelocityOneColumn</value>
</constructor-arg>
</bean>

方法二:使用注解区分Bean

(未完 待续)

相关推荐
python开发_常用的python模块及安装方法
adodb:我们领导推荐的数据库连接组件bsddb3:BerkeleyDB的连接组件Cheetah-1.0:我比较喜欢这个版本的cheeta…
日期:2022-11-24 点赞:878 阅读:8,956
Educational Codeforces Round 11 C. Hard Process 二分
C. Hard Process题目连接:http://www.codeforces.com/contest/660/problem/CDes…
日期:2022-11-24 点赞:807 阅读:5,480
下载Ubuntn 17.04 内核源代码
zengkefu@server1:/usr/src$ uname -aLinux server1 4.10.0-19-generic #21…
日期:2022-11-24 点赞:569 阅读:6,327
可用Active Desktop Calendar V7.86 注册码序列号
可用Active Desktop Calendar V7.86 注册码序列号Name: www.greendown.cn Code: &nb…
日期:2022-11-24 点赞:733 阅读:6,110
Android调用系统相机、自定义相机、处理大图片
Android调用系统相机和自定义相机实例本博文主要是介绍了android上使用相机进行拍照并显示的两种方式,并且由于涉及到要把拍到的照片显…
日期:2022-11-24 点赞:512 阅读:7,741
Struts的使用
一、Struts2的获取  Struts的官方网站为:http://struts.apache.org/  下载完Struts2的jar包,…
日期:2022-11-24 点赞:671 阅读:4,776