Affects: 2.5.4

Not all the properties are loaded when the bean is loaded based on the condition present in the configuration. Without the condition the values are loaded correctly.

   ```
@Bean
@ConditionalOnExpression("#{appProperties.approach2 eq false}")
public String approch2(AppProperties properties) {
    System.out.println(properties.message); //prints null
    System.out.println(properties.degree); //prints 0
    return "";
}

application.properties

application.message="some message" application.degree=5 application.approach1=true application.approach2=false

---


**Comment From: snicoll**

@vvijayv the environment is prepared before the application context is refreshed. You are mentioning `application.properties` which is part of that for. To make some progress, please take the time to share a minimal sample that reproduces the problem (no code snippet in text, but an actual project we can run ourselves). You can do so by attaching a zip to this issue or sharing a link to a GitHub repository. Thank you.

**Comment From: vvijayv**

Hi @snicoll I have attached a sample project you can test this
[conditional-bug-test.zip](https://github.com/spring-projects/spring-framework/files/7568311/conditional-bug-test.zip)


**Comment From: snicoll**

Thanks. `ConditionalOnExpression` on a configuration properties bean leads to some early initialization of the bean which, somehow, means that binding does not occur at all.

**Comment From: vvijayv**

I have to make this work with this, `@ConditionalOnProperty(prefix = "appProperties", name = "approach2", havingValue = "false")`

It would be good if the lifecycle of the conditional annotations are almost same

**Comment From: wilkinsona**

I'm not sure there's anything that we can do about this in Spring Boot other than adding a warning to the javadoc of `@ConditionalOnExpression`. The SpEL expression is evaluated as part of configuration class parsing and that's out of Boot's control.

I'm a little surprised that Framework's `BeanPostProcessorChecker` doesn't log an info message stating that `appProperties` won't be eligible for post-processing. The message is missing as the condition is evaluated as part of refresh's call to `invokeBeanFactoryPostProcessors(beanFactory)`. Here's the stack of `AppProperties` being instantiated due to the SpEL expression's evaluation:

Thread [main] (Suspended (entry into method in AppProperties))
owns: ConcurrentHashMap (id=50)
owns: Object (id=51)
AppProperties.() line: 16 NativeConstructorAccessorImpl.newInstance0(Constructor<?>, Object[]) line: not available [native method]
NativeConstructorAccessorImpl.newInstance(Object[]) line: 62
DelegatingConstructorAccessorImpl.newInstance(Object[]) line: 45
Constructor.newInstance(Object...) line: 490 BeanUtils.instantiateClass(Constructor, Object...) line: 211 CglibSubclassingInstantiationStrategy(SimpleInstantiationStrategy).instantiate(RootBeanDefinition, String, BeanFactory) line: 87
DefaultListableBeanFactory(AbstractAutowireCapableBeanFactory).instantiateBean(String, RootBeanDefinition) line: 1326
DefaultListableBeanFactory(AbstractAutowireCapableBeanFactory).createBeanInstance(String, RootBeanDefinition, Object[]) line: 1232
DefaultListableBeanFactory(AbstractAutowireCapableBeanFactory).doCreateBean(String, RootBeanDefinition, Object[]) line: 582 DefaultListableBeanFactory(AbstractAutowireCapableBeanFactory).createBean(String, RootBeanDefinition, Object[]) line: 542
DefaultListableBeanFactory(AbstractBeanFactory).lambda$doGetBean$0(String, RootBeanDefinition, Object[]) line: 335
1278839936.getObject() line: not available
DefaultListableBeanFactory(DefaultSingletonBeanRegistry).getSingleton(String, ObjectFactory<?>) line: 234
DefaultListableBeanFactory(AbstractBeanFactory).doGetBean(String, Class, Object[], boolean) line: 333
DefaultListableBeanFactory(AbstractBeanFactory).getBean(String) line: 208
BeanFactoryResolver.resolve(EvaluationContext, String) line: 51 BeanReference.getValueInternal(ExpressionState) line: 55
CompoundExpression.getValueRef(ExpressionState) line: 55
CompoundExpression.getValueInternal(ExpressionState) line: 91
OpEQ.getValueInternal(ExpressionState) line: 42 OpEQ.getValueInternal(ExpressionState) line: 32 OpEQ(SpelNodeImpl).getValue(ExpressionState) line: 112
SpelExpression.getValue(EvaluationContext) line: 272
StandardBeanExpressionResolver.evaluate(String, BeanExpressionContext) line: 167
OnExpressionCondition.evaluateExpression(ConfigurableListableBeanFactory, String) line: 60
OnExpressionCondition.getMatchOutcome(ConditionContext, AnnotatedTypeMetadata) line: 48 OnExpressionCondition(SpringBootCondition).matches(ConditionContext, AnnotatedTypeMetadata) line: 47
ConditionEvaluator.shouldSkip(AnnotatedTypeMetadata, ConfigurationCondition$ConfigurationPhase) line: 108
ConfigurationClassBeanDefinitionReader.loadBeanDefinitionsForBeanMethod(BeanMethod) line: 193
ConfigurationClassBeanDefinitionReader.loadBeanDefinitionsForConfigurationClass(ConfigurationClass, ConfigurationClassBeanDefinitionReader$TrackedConditionEvaluator) line: 153 ConfigurationClassBeanDefinitionReader.loadBeanDefinitions(Set) line: 129
ConfigurationClassPostProcessor.processConfigBeanDefinitions(BeanDefinitionRegistry) line: 343
ConfigurationClassPostProcessor.postProcessBeanDefinitionRegistry(BeanDefinitionRegistry) line: 247 PostProcessorRegistrationDelegate.invokeBeanDefinitionRegistryPostProcessors(Collection, BeanDefinitionRegistry, ApplicationStartup) line: 311 PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory, List) line: 112
AnnotationConfigApplicationContext(AbstractApplicationContext).invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory) line: 746
AnnotationConfigApplicationContext(AbstractApplicationContext).refresh() line: 564
SpringApplication.refresh(ConfigurableApplicationContext) line: 765 SpringApplication.refreshContext(ConfigurableApplicationContext) line: 445
SpringApplication.run(String...) line: 338
SpringApplication.run(Class<?>[], String[]) line: 1354
SpringApplication.run(Class<?>, String...) line: 1343
ConditionalBugTestApplication.main(String[]) line: 14
```

The checker isn't registered until the next line in refresh() where registerBeanPostProcessors(beanFactory) is called. It's also at this point that the post-processor for configuration property binding would be registered which explains why the properties are not bound when the SpEL expression evaluation triggers early initialisation of the bean.

I wonder if the registration of BeanPostProcessorChecker could be brought forward so that it happens before configuration class parsing?

Comment From: jhoeller

Bringing BeanPostProcessorChecker forward would mean bringing the BeanPostProcessor bean type retrieval forward, and that's a tough pill to swallow. From that perspective, I don't see us improving the warning situation here; we'll have to rely on documentation.