Reputation: 607
Is there any way to detect wether a bean is lazily initialized that works reliably and for every bean in context?
In particular a bean such as this one:
@Configuration
class MyConfig() {
@Bean
@Lazy
Foo foo() {
return new Foo();
}
I could not find any way to programmatically detect 'foo' is lazy.
Other kind of lazy beans such as this:
@Lazy
@Component
class Bar {
...
}
can be detected with something like:
boolean isLazy = applicationContext.findAnnotationOnBean(beanName, Lazy.class) != null
this is not reliable, it can produce false-positives, for example if a Bar
bean is part of a configuration that initializes it eagerly.
Upvotes: 1
Views: 1706
Reputation: 42184
You can use ConfigurableListableBeanFactory.getBeanDefinition(String name)
to get BeanDefinition
instance and call BeanDefinition.isLazyInit()
to get information if following bean is initialized using lazy initialization. It works for both cases described by you - when @Lazy
is used on class and on bean factory method. Take a look at following example that load prints out all beans that are loaded lazily:
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Lazy;
@SpringBootApplication
public class Application {
@Bean
@Lazy
public Foo foo() {
return new Foo();
}
public static void main(String[] args) {
final ConfigurableApplicationContext ctx = SpringApplication.run(Application.class, args);
ctx.getBeanFactory().getBeanNamesIterator().forEachRemaining(bean -> {
try {
final BeanDefinition beanDefinition = ctx.getBeanFactory().getBeanDefinition(bean);
if (beanDefinition.isLazyInit()) {
System.out.println("Bean '" + bean + "' is lazy initialized...");
}
} catch (NoSuchBeanDefinitionException e) {}
});
}
static class Foo {
private boolean bar = true;
}
}
When I run it I see following part in the console:
Bean 'otherLazyBean' is lazy initialized...
Bean 'foo' is lazy initialized...
Bean 'mvcHandlerMappingIntrospector' is lazy initialized...
This otherLazyBean
is a component class annotated with @Lazy
annotation. Hope it helps.
Upvotes: 2