Вот решение, к которому я пришел (благодаря Javashlook, чей ответ поставил меня на правильный путь). Это работает, но, скорее всего, это не способ производства.
Но лучше, чем тысяча слов, вот код, я вам позволю судить сам.
Давайте посмотрим на пересмотренное перечисление Car
:
public enum Car {
NANO(CarEnumerationInitializer.getNANO()), MERCEDES(
CarEnumerationInitializer.getMERCEDES()), FERRARI(
CarEnumerationInitializer.getFERRARI());
public final String cost;
public final String madeIn;
Car(ICarProperties properties) {
this.cost = properties.getCost();
this.madeIn = properties.getMadeIn();
}
}
А вот и "отвесные" классы:
//Car's properties placeholder interface ...
public interface ICarProperties {
public String getMadeIn();
public String getCost();
}
//... and its implementation
public class CarProperties implements ICarProperties {
public final String cost;
public final String madeIn;
public CarProperties(String cost, String madeIn) {
this.cost = cost;
this.madeIn = madeIn;
}
@Override
public String getCost() {
return this.cost;
}
@Override
public String getMadeIn() {
return this.madeIn;
}
}
//Singleton that will be provide Car's properties, that will be defined at applicationContext loading.
public final class CarEnumerationInitializer {
private static CarEnumerationInitializer INSTANCE;
private static ICarProperties NANO;
private static ICarProperties MERCEDES;
private static ICarProperties FERRARI;
private CarEnumerationInitializer(ICarProperties nano,
ICarProperties mercedes, ICarProperties ferrari) {
CarEnumerationInitializer.NANO = nano;
CarEnumerationInitializer.MERCEDES = mercedes;
CarEnumerationInitializer.FERRARI = ferrari;
}
public static void forbidInvocationOnUnsetInitializer() {
if (CarEnumerationInitializer.INSTANCE == null) {
throw new IllegalStateException(CarEnumerationInitializer.class
.getName()
+ " unset.");
}
}
public static CarEnumerationInitializer build(CarProperties nano,
CarProperties mercedes, CarProperties ferrari) {
if (CarEnumerationInitializer.INSTANCE == null) {
CarEnumerationInitializer.INSTANCE = new CarEnumerationInitializer(
nano, mercedes, ferrari);
}
return CarEnumerationInitializer.INSTANCE;
}
public static ICarProperties getNANO() {
forbidInvocationOnUnsetInitializer();
return NANO;
}
public static ICarProperties getMERCEDES() {
forbidInvocationOnUnsetInitializer();
return MERCEDES;
}
public static ICarProperties getFERRARI() {
forbidInvocationOnUnsetInitializer();
return FERRARI;
}
}
Наконец, определение контекста приложения:
<?xml version="1.0" encoding="UTF-8"?>
<beans>
<bean id="nano" class="be.vinkolat.poc.core.car.CarProperties">
<constructor-arg type="java.lang.String" value="Cheap"></constructor-arg>
<constructor-arg type="java.lang.String" value="India"></constructor-arg>
</bean>
<bean id="mercedes"
class="be.vinkolat.poc.core.car.CarProperties">
<constructor-arg type="java.lang.String" value="Expensive"></constructor-arg>
<constructor-arg type="java.lang.String" value="Germany"></constructor-arg>
</bean>
<bean id="ferrari" class="be.vinkolat.poc.core.car.CarProperties">
<constructor-arg type="java.lang.String"
value="Very Expensive">
</constructor-arg>
<constructor-arg type="java.lang.String" value="Italy"></constructor-arg>
</bean>
<bean id="carInitializer"
class="be.vinkolat.poc.core.car.CarEnumerationInitializer"
factory-method="build" lazy-init="false">
<constructor-arg type="be.vinkolat.poc.core.car.CarProperties"
ref="nano" />
<constructor-arg type="be.vinkolat.poc.core.car.CarProperties"
ref="mercedes" />
<constructor-arg type="be.vinkolat.poc.core.car.CarProperties"
ref="ferrari" />
</bean>
</beans>
Это работает, но есть один существенный недостаток: CarEnumerationInitializer
ДОЛЖЕН создаваться экземпляр ДО ТОГО, как делается ссылка на перечисление Car
, в противном случае CarProperties имеют значение null, что означает, что свойства Car не могут быть установлены при загрузке Car
(следовательно, IllegalStateException
брошено, чтобы, по крайней мере, заставить его падать предсказуемо и задокументировано). Для свойства carInitializer
bean lazy-init
установлено явное значение false
, чтобы подчеркнуть необходимость его загрузки как можно скорее.
Я бы сказал, что это может быть полезно в простом приложении, в котором можно легко угадать, где будет сделан первый вызов Car
. Для большего размера это, вероятно, будет такой беспорядок, что я не рекомендовал вам использовать его.
Надеюсь, эта помощь, комментарии и голосование (вверх и вниз) очень приветствуются :) Я подожду несколько дней, чтобы сделать этот ответ приемлемым, чтобы вы могли среагировать.