Spring has a nice @Conditional annotation, to have the option to have beans be available in the context depending a specific condition (Of course, this can also be realized by using @Configuration objects, but that's a different post).
Ideally, we'd have the option to have a condition evaluate to true or false depending on a property. Sadly, Spring does not support that out of the box.
Googling and looking around gives a partial solution, but the complete one here, so we won't forget:
This allows us to have a service or component be available or not upon startup
Moreover, it allows us to define two beans *under the same name*, as in:
Ideally, we'd have the option to have a condition evaluate to true or false depending on a property. Sadly, Spring does not support that out of the box.
Googling and looking around gives a partial solution, but the complete one here, so we won't forget:
/** * Components annotated with ConditionalOnProperty will be registered in the spring context depending on the value of a * property defined in the propertiesBeanName properties Bean. */ @Target({ ElementType.TYPE, ElementType.METHOD }) @Retention(RetentionPolicy.RUNTIME) @Conditional(OnPropertyCondition.class) public @interface ConditionalOnProperty { /** * The name of the property. If not found, it will evaluate to false. */ String value(); /** * if the properties value should be true (default) or false */ boolean on() default true; /** * Name of the bean containing the properties. */ String propertiesBeanName(); } /** * Condition that matches on the value of a property. * * @see ConditionalOnProperty */ class OnPropertyCondition implements ConfigurationCondition { private static final Logger LOG = LoggerFactory.getLogger(OnPropertyCondition.class); @Override public boolean matches(final ConditionContext context, final AnnotatedTypeMetadata metadata) { final Mapattributes = metadata.getAnnotationAttributes(ConditionalOnProperty.class.getName()); final String propertyName = (String) attributes.get("value"); final String propertiesBeanName = (String) attributes.get("propertiesBeanName"); final boolean propertyDesiredValue = (boolean) attributes.get("on"); // for some reason, we cannot use the environment here, hence we get the actual properties bean instead. Properties props = context.getBeanFactory().getBean(propertiesBeanName, Properties.class); final boolean propValue = parseBoolean(props.getProperty(propertyName, Boolean.toString(false))); LOG.info("Property '{}' resolved to {}, desired: {}", new Object[] { propertyName, propValue, "" + propertyDesiredValue }); return propValue == propertyDesiredValue; } /** * Set the registration to REGISTER, else it is handled during the parsing of the configuration file * and we have no guarantee that the properties bean is loaded/exposed yet */ @Override public ConfigurationPhase getConfigurationPhase() { return ConfigurationPhase.REGISTER_BEAN; } }
@ConditionalOnProperty(value="usenew", on=false, propertieBeanName="myprops") @Service("service") public class oldService implements ServiceFunction{ // some old implementaion of the service function. } @ConditionalOnProperty(value="usenew", on=true, propertieBeanName="myprops") @Service("service") public class newService implements ServiceFunction{ // some new implementaion of the service function. }
Reacties
Een reactie posten