Using Spring IoC to set up enum values

2020-01-27 03:47发布

Is there a way to set up such enum values via Spring IoC at construction time?

What I would like to do is to inject, at class load time, values that are hard-coded in the code snippet below:

public enum Car
{
        NANO ("Very Cheap", "India"),
        MERCEDES ("Expensive", "Germany"),
        FERRARI ("Very Expensive", "Italy");

        public final String cost;
        public final String madeIn;

        Car(String cost, String madeIn)
        {
                this.cost= cost;
                this.madeIn= madeIn;
        }

}

Let's say that the application must be deployed in Germany, where Nanos are "Nearly free", or in India where Ferraris are "Unaffordable". In both countries, there are only three cars (deterministic set), no more no less, hence an enum, but their "inner" values may differ. So, this is a case of contextual initialization of immutables.

13条回答
相关推荐>>
2楼-- · 2020-01-27 04:17

Do you mean setting up the enum itself?

I don't think that's possible. You cannot instantiate enums because they have a static nature. So I think that Spring IoC can't create enums as well.

On the other hand, if you need to set initialize something with a enum please check out the Spring IoC chapter. (search for enum) There's a simple example that you can use.

查看更多
Summer. ? 凉城
3楼-- · 2020-01-27 04:19
<bean id="car" class="Foo">
    <property name="carString" value="NANO" />
</bean>

And then in your class Foo, you would have this setter:

public void setCar(String carString) {
    this.carString = Car.valueOf(carString);
}
查看更多
我欲成王,谁敢阻挡
4楼-- · 2020-01-27 04:24

I have done it in the following way:

@Component
public class MessageSourceHelper {
    @Inject
    public MessageSource injectedMessageSource;

    public static MessageSource messageSource;

    public static String getMessage(String messageKey, Object[] arguments, Locale locale) {
        return messageSource.getMessage(messageKey, arguments, locale);
    }

    @PostConstruct
    public void postConstruct() {
        messageSource = injectedMessageSource;
    }

}

That way you can easily use it in the enum to get messages in the following way:

MessageSourceHelper.getMessage(key, arguments, locale);
查看更多
放荡不羁爱自由
5楼-- · 2020-01-27 04:24

You can use Enum class as factory bean. Example: setting serializationInclusion field with enum value:

            <property name="serializationInclusion">
                <bean class="org.codehaus.jackson.map.annotate.JsonSerialize.Inclusion" factory-method="valueOf">
                    <constructor-arg>   
                        <value>NON_NULL</value>
                    </constructor-arg>
                </bean>
            </property>

But actually (Spring 3.1) a simpler solution works: you just write the enum value and Spring recognizes what to do:

<property name="serializationInclusion" value="NON_NULL"/>
查看更多
Explosion°爆炸
6楼-- · 2020-01-27 04:25

What do you need to set up? The values are created when the class loads, and as it's an enum, no other values can be created (unless you add them to the source and recompile).

That's the point of an enum, to be able to give limit a type to an explicit range of constant, immutable values. Now, anywhere in your code, you can refer to a type Car, or its values, Car.NANO, Car.MERCEDES, etc.

If, on the other hand, you have a set of values that isn't an explicit range, and you want to be able to create arbitrary objects of this type, you'd use the same ctor as in your post, but as a regular, not enum class. Then Spring provides various helper clases to read values from some source (XML file, config file, whatever) and create Lists of that type.

查看更多
7楼-- · 2020-01-27 04:26

Why not provide a setter (or constructor argument) that takes a String, and simply call Enum.valueOf(String s) to convert from a String to an enum. Note an exception will get thrown if this fails, and your Spring initialisation will bail out.

查看更多
登录 后发表回答