Home > Software design >  Bean is created regardless of @ConditionalOnProperty matchIfMissing's value
Bean is created regardless of @ConditionalOnProperty matchIfMissing's value

Time:10-01

I am trying to create a bean for cacheManager only when a specific cachemanager is not configured.

@Bean
@ConditionalOnProperty(name = "spring.cache.type", matchIfMissing = true)
public CacheManager cacheManager() {
ConcurrentMapCacheManager cacheManager = new ConcurrentMapCacheManager() {

  @Override
  protected Cache createConcurrentMapCache(final String name) {
    return new ConcurrentMapCache(name,
      CacheBuilder.newBuilder().expireAfterWrite(30, TimeUnit.SECONDS).build().asMap(), false);
  }
};

return cacheManager;
}

This bean is created even when I have the property

spring.cache.type=redis

is configured. Did try different combinations with prefix with no luck. This bean is injected regardless of whether the cache type is specified or not in the application.properties.

CodePudding user response:

The issue seems to be that the default value of having attribute does not work as you expect it to. Reading the enter image description here

Having said all that I would say that your best option would be to create your own Condition just like @ray suggested.

CodePudding user response:

Your issue is quite straightforward. You need to understand what is actually happening here.

As you already knows @ConditionalOnProperty creates a bean when the propert specify in your annotation is available in your yml. In your case it is spring.cache.type.

So if you annotate like this @ConditionalOnProperty(name = "spring.cache.type"), bean will not created when property not is not available. In other words "condition is false because condition is absent".

When you annotate like this @ConditionalOnProperty(name = "spring.cache.type", matchIfMissing = true), bean will created when the property not available because we explicitly mention that by matchIfMissing = true. In other words "assume condition is true when property is absent". So obviously condition is true when the property is available.

So to fix your issue what you can do something like this, define a havingValue that will never put as the value for that property. What happens then, bean will not created even when property is available because value of that property does matches your havingValue.

Something like this,

@ConditionalOnProperty(name = "spring.cache.type", matchIfMissing = true, havingValue = "none")

Method 2

You can create custom Condition class. Like follows,

public class ConditionalOnMisssing implements Condition {
    @Override
    public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
        Environment env = context.getEnvironment();
        return env.getProperty("spring.cache.type") == null;
    }
}

Then change your CacheManager bean as follows.

@Bean
@Conditional(ConditionalOnMisssing.class)
public CacheManager cacheManager() {}
  • Related