Print All the Spring Beans That Are Loaded

Print all the Spring beans that are loaded

Yes, get ahold of ApplicationContext and call .getBeanDefinitionNames()

You can get the context by:

  • implementing ApplicationContextAware
  • injecting it with @Inject / @Autowired (after 2.5)
  • use WebApplicationContextUtils.getRequiredWebApplicationContext(..)

Related: You can also detect each bean's registration by registering a BeanPostprocessor bean. It will be notified for each bean.

Print all the Spring beans that are loaded - Spring Boot

As shown in the getting started guide of spring-boot: https://spring.io/guides/gs/spring-boot/

@SpringBootApplication
public class Application {

public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}

@Bean
public CommandLineRunner commandLineRunner(ApplicationContext ctx) {
return args -> {

System.out.println("Let's inspect the beans provided by Spring Boot:");

String[] beanNames = ctx.getBeanDefinitionNames();
Arrays.sort(beanNames);
for (String beanName : beanNames) {
System.out.println(beanName);
}
};
}
}

As @Velu mentioned in the comments, this will not list manually registered beans.

In case you want to do so, you can use getSingletonNames(). But be careful. This method only returns already instantiated beans. If a bean isn't already instantiated, it will not be returned by getSingletonNames().

List all my beans loaded by SpringApplication.run

Using ConfigurableApplicationContext you can get all bean types. For example:

@Autowired
ConfigurableApplicationContext context;
.....
ConfigurableListableBeanFactory beansFactory = context.getBeanFactory();
String[] beansNames = beansFactory.getBeanDefinitionNames();
Set<String> beansType = new HashSet<>();

for(String beanName : beansNames){
if (beanName.matches("(.*)Controller")){
beansType.add(beansFactory.getType(beanName).toString());
}
}

Other easier option to show all the beans is
In the case you are using spring-web You could use Spring boot actuator. Add the next dependency in your pom.xml and go to the /bean endpoint to show all beans, and it will put the name of the bean and the class.

Check which beans have loaded in spring context

At startup, Spring logs at info level the names of all the beans being loaded by a context. Or in code, you can use getBeanDefinitionNames() to get all the bean names.

How to list all loaded Spring bean definition files

When starting a ClassPathXmlApplicationContext or more generally an AbstractXmlApplicationContext, an XmlBeanDefinitionReader will be used to load your xml files.

Each time an xml file will be loaded, to be precise before it gets loaded, you'll have a log (info) from loadBeanDefinitions(EncodedResource encodedResource) :

    if (logger.isInfoEnabled()) {
logger.info("Loading XML bean definitions from " + encodedResource.getResource());
}

If you can't rely on this information you can play with ReaderEventListener :

public class TrackingImportXmlApplicationContext extends ClassPathXmlApplicationContext {

private static final TrackingImportReaderEventListener trackingImportReaderEventListener = new TrackingImportReaderEventListener();

public TrackingImportXmlApplicationContext(String configLocation) {
super(configLocation);
}

public TrackingImportXmlApplicationContext(String... configLocations) {
super(configLocations);
}

@Override
protected void initBeanDefinitionReader(XmlBeanDefinitionReader reader) {
super.initBeanDefinitionReader(reader);
reader.setEventListener(trackingImportReaderEventListener);
}

public TrackingImportReaderEventListener getTrackingImportReaderEventListener() {
return trackingImportReaderEventListener;
}

public static class TrackingImportReaderEventListener extends EmptyReaderEventListener {

private final Set<String> imports = new HashSet<>();

@Override
public void importProcessed(ImportDefinition importDefinition) {
imports.add(importDefinition.getImportedResource());
}

public Set<String> getImports() {
return imports;
}
}
}

And then :

public class Main {

public static void main(String[] args) {
TrackingImportXmlApplicationContext applicationContext = new TrackingImportXmlApplicationContext("/META-INF/applicationContext.xml");
TrackingImportXmlApplicationContext.TrackingImportReaderEventListener tracking = applicationContext.getTrackingImportReaderEventListener();
for (String _import : tracking.getImports()) {
System.out.println(" >>> imported : " + _import);
}
}
}

In this later solution you'll only have imported file, but of course you already know your initial xml file(s)

How can I check if a bean has been loaded by springboot

The below code will log all the beans being loaded by spring application in its container:-

@SpringBootApplication
public class Application implements CommandLineRunner {

@Autowired
private ApplicationContext appContext;

public static void main(String[] args) throws Exception {
SpringApplication.run(Application.class, args);
}

@Override
public void run(String... args) throws Exception {

String[] beans = appContext.getBeanDefinitionNames();
Arrays.sort(beans);
for (String bean : beans) {
System.out.println(bean);
}

}
}

In spring are all the beans created at the time of container creation

By default yes. All beans get created on startup. There's the @Lazy annotation which allows you to delay the initialization until the bean gets used.

View all Spring Configuration files loaded so far

You can use ApplicationContext#getBeansWithAnnotation. It will not only take classes with @Configuration annotation but also classes annotated with annotations meta-annotated with @Configuration, like @SpringBootApplication:

@Bean
ApplicationRunner applicationRunner(ApplicationContext applicationContext) {
return args -> {
applicationContext.getBeansWithAnnotation(Configuration.class)
.entrySet()
.stream()
.filter(entry -> entry.getValue().getClass().getPackage().getName().startsWith("com.your.package"))
.forEach(entry -> {
System.out.println("name: " + entry.getKey() + ", bean: " + entry.getValue());
});
};
}

Print non-managed Spring bean name

Here my understading it that bean will live in Spring Container till i
shutdown the server

Your understanding is wrong it will die with the request i.e. the scope of the object is within that method(processBean) only. The container will NOT manage your bean. Apart from that, there is no sense in using

@Autowired in your non managed bean. Since container doenn't manage it it will be null (unless you inject it using beanFactory.autowireBean();) and therefore answer to your question that if you can print any such bean using spring services is NO

How to Lazy load all the Spring beans whether it is defined by @Bean or @Component in Springboot 2.2

I think you misunderstood the meaning of the lazy flag you are passing,
It means that the object will be created only when it is invoked but it does not say that it will not scan that package. Spring will scan all packages and store bean definition names but it will create the objects only when it is invoked, if you have passed the lazy flag to it.

You can verify this behaviour by checking the number of beans created when you pass the lazy flag as true and false.
you can check it as given below

ApplicationContext context = SpringApplication.run(SpringBootApplication.class, args);
System.out.println("count:"+context.getBeanDefinitionCount());

Edit on Apr/7th 2020 start

Another way to do that is create a constructor and use that to inject the autowired properties and print out a log when they enter the constructor.

I did the same in a sample project and below is he result, first one is for eager initialization and next one for lazy.

spring.main.lazy-initialization=false
Application logs

Inside Constructor
calling bean
inside bean method

spring.main.lazy-initialization=true
Application logs

calling bean
Inside Constructor
inside bean method

Edit on Apr/7th 2020 end

Please mark this as answered if I answered your question.
Thank you



Related Topics



Leave a reply



Submit