简体   繁体   中英

Is it possible to alias bean class names in Spring?

I have a string property which looks similar to the following example:

<property name="mappingData">
  <list>                
    <bean class="com.company.product.longNamingStandard.migration.extractor.FieldMapping">
      <property name="elementName" value="entitlement.user"/>
      <property name="mapping" value="DocUsers"/>
    </bean>
    <bean class="com.company.product.longNamingStandard.migration.extractor.FieldMapping">
      <property name="elementName" value="entitlement.contributor"/>
      <property name="mapping" value="DocContributors"/>
    </bean>
  </list>
</property>  

The long class name(s) effect readability & also create a refactoring overhead.

Is it possible to alias the class name and use a short name to declare the beans? Or is there an alternate best practice I'm missing?

Probably a bit late for you, but hopefully useful for others:

You can use parent beans to accomplish this. First declare a parent bean as a template:

<bean id="FieldMapping" class="com.company.product.longNamingStandard.migration.extractor.FieldMapping"/>

Then use it elsewhere, using the parent attribute.

<property name="mappingData">
  <list>                
    <bean parent="FieldMapping">
      <property name="elementName" value="entitlement.user"/>
      <property name="mapping" value="DocUsers"/>
    </bean>
    <bean parent="FieldMapping">
      <property name="elementName" value="entitlement.contributor"/>
      <property name="mapping" value="DocContributors"/>
    </bean>
  </list>
</property>

Please note my convention here is to use upper case id's here for the parent template beans.

each <bean/> comes with an attribute of name and id to help you reference those beans later in your configuration.

I would suggest using the id for declaring the bean.

your config could look like:

<bean id="fooBean" class="com.example.foo"/>
<bean id="barBean" class="com.example.bar"/>

<list>
   <ref>fooBean</ref>
   <ref>barBean</ref>
</list>

You may try to represent your mapping in some short form, and then convert it to the list of FieldMapping s. For example, mappings from your snippet may be represented as a map.

As a theoretic exercise in Spring 3 you can do this with Spring Expression Language (if FieldMapping has the apropriate constructor):

<util:map id = "m">
    <entry name = "entitlement.user" value = "DocUsers" />
    <entry name = "entitlement.contributor" value = "DocContributors" />
</util:map>
...
<property name = "mappingData" 
    value = "#{m.![new com.company.product.longNamingStandard.migration.extractor.FieldMapping(key, value)]}" />

If this expression is too obscure, you may implement a FactoryBean to take a short form of your mapping data (for example, a map, as in this example) and return a configured list of FieldMapping s:

<property name = "mappingData">
    <bean class = "FieldMappingListFactoryBean">
        <property name = "mappings">
            <map>
                <entry name = "entitlement.user" value = "DocUsers" />
                <entry name = "entitlement.contributor" value = "DocContributors" />
            </map>
        </property>
    </bean>
</property>

However, if your field mappings are some kind of reusable DSL, you may try to think about implementing a namespace extension .

I found a way to simulate an effect similar to a "import com.Foo;" in java code. The best option I could find was to use a PropertyPlaceholderConfigurer with local properties defined. Using your example, here's the configuration that you would put at the top of your spring config file to define a "class_FieldMapping" property:

<bean
    class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
    <description>Define properties equivalent to "import foo;" in java source</description>
    <property name="properties">
        <props>
            <prop key="class_FieldMapping">com.company.product.longNamingStandard.migration.extractor.FieldMapping</prop>
        </props>
    </property>
</bean>

Then, you can use that property within your beans:

<property name="mappingData">
  <list>                
    <bean class="${class_FieldMapping}">
      ...
    </bean>
    <bean class="${class_FieldMapping}">
      ...
    </bean>
  </list>
</property>

This has the benefit that use can also use it for things where you actually need the class name, and can't reference an instance of an object:

<util:constant static-field="${class_FieldMapping}.MYSTATICVAR" />

If I use PropertyPlaceholderConfigurer it leads to several exceptions in debug log. It works, but it seems it doesn't work on the first try.

为什么不将这些内部bean声明为具有自己名称的单独的顶级bean,然后在列表中引用它们?

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM