@Configuration classes are turned into beans and stored in the application context. Spring will sometimes query the class of every bean to see if it has been annotated with a particular annotation, for example to find @Controllers or @Aspects. This is typically done with AnnotationUtils.findAnnotation(…) which will fail with a very cryptic java.lang.ArrayStoreException: sun.reflect.annotation.TypeNotPresentExceptionProxy if any of the annotations it encounters refer to classes that cannot be loaded. This will always be the case with @ConditionalOnMissingClass: the only way for the bean that represents the configuration to be in the application context is if the class that it refers to is missing. It may be the case for @ConditionalOnMissingBean.
To avoid problems with @ConditionalOnMissingBean it should either be used on @Bean methods, or be protected with an @ConditionalOnClass annotation. Flyway's auto-configuration is a good example of the latter:
@Configuration
@ConditionalOnClass(Flyway.class)
@ConditionalOnBean(DataSource.class)
@ConditionalOnExpression("${flyway.enabled:true}")
@AutoConfigureAfter(DataSourceAutoConfiguration.class)
public class FlywayAutoConfiguration {
@Configuration
@ConditionalOnMissingBean(Flyway.class)
@EnableConfigurationProperties(FlywayProperties.class)
@Import(FlywayJpaDependencyConfiguration.class)
public static class FlywayConfiguration {
Note the @ConditionalOnClass(Flyway.class) on FlywayAutoConfiguration that makes it safe to use @ConditionalOnMissingBean(Flyway.class) on the nested FlywayConfiguration
To avoid potential problems with @ConditionalOnMissingClass I think it has to either be on an @Bean method or, if it's used on a class, then the class must be referred to by name, i.e. as a String, rather than as a Class. At the time of writing, SocialWebAutoConfiguration.AnonymousUserIdSourceConfig is the only class-level user of @ConditionalOnMissingClass where the class is referenced directly, rather than by name.