docs
Package: org.springframework.boot.builder
Primary Class: SpringApplicationBuilder
Since: 1.0.0
Fluent API builder for SpringApplication and ApplicationContext instances with support for context hierarchies. Provides method chaining for convenient configuration of Spring Boot applications.
SpringApplicationBuilder provides a fluent builder API for creating and configuring SpringApplication instances. Unlike SpringApplication's setter methods (which return void), all SpringApplicationBuilder methods return the builder instance, enabling method chaining.
Key Features:
// SpringApplication - requires multiple statements
SpringApplication app = new SpringApplication(MyApp.class);
app.setWebApplicationType(WebApplicationType.SERVLET);
app.setBannerMode(Banner.Mode.OFF);
app.setLogStartupInfo(false);
app.run(args);
// SpringApplicationBuilder - fluent chaining
new SpringApplicationBuilder(MyApp.class)
.web(WebApplicationType.SERVLET)
.bannerMode(Banner.Mode.OFF)
.logStartupInfo(false)
.run(args);// Parent-child context hierarchy
new SpringApplicationBuilder(ParentConfig.class)
.child(ChildConfig.class)
.run(args);
// Sibling contexts
new SpringApplicationBuilder(MainConfig.class)
.sibling(SiblingConfig.class)
.run(args);package org.springframework.boot.builder;
import org.springframework.boot.ApplicationContextFactory;
import org.springframework.boot.Banner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.WebApplicationType;
import org.springframework.boot.bootstrap.BootstrapRegistryInitializer;
import org.springframework.beans.factory.support.BeanNameGenerator;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextInitializer;
import org.springframework.context.ApplicationListener;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.core.env.ConfigurableEnvironment;
import org.springframework.core.io.ResourceLoader;
import org.springframework.core.metrics.ApplicationStartup;
import java.util.Map;
import java.util.Properties;
/**
* Builder for SpringApplication with fluent API and context hierarchy support.
* @since 1.0.0
*/
public class SpringApplicationBuilder {
// Constructors
public SpringApplicationBuilder(Class<?>... sources);
public SpringApplicationBuilder(ResourceLoader resourceLoader, Class<?>... sources);
// Build and run
public ConfigurableApplicationContext run(String... args);
public SpringApplication build();
public SpringApplication build(String... args);
// Access current state
public SpringApplication application();
public ConfigurableApplicationContext context();
// Context hierarchy
public SpringApplicationBuilder child(Class<?>... sources);
public SpringApplicationBuilder parent(Class<?>... sources);
public SpringApplicationBuilder parent(ConfigurableApplicationContext parent);
public SpringApplicationBuilder sibling(Class<?>... sources);
public SpringApplicationBuilder sibling(Class<?>[] sources, String... args);
// Configuration sources
public SpringApplicationBuilder sources(Class<?>... sources);
// Application type
public SpringApplicationBuilder web(WebApplicationType webApplicationType);
// Logging and banner
public SpringApplicationBuilder logStartupInfo(boolean logStartupInfo);
public SpringApplicationBuilder banner(Banner banner);
public SpringApplicationBuilder bannerMode(Banner.Mode bannerMode);
// System configuration
public SpringApplicationBuilder headless(boolean headless);
public SpringApplicationBuilder registerShutdownHook(boolean registerShutdownHook);
public SpringApplicationBuilder main(Class<?> mainApplicationClass);
// Properties and profiles
public SpringApplicationBuilder addCommandLineProperties(boolean addCommandLineProperties);
public SpringApplicationBuilder setAddConversionService(boolean addConversionService);
public SpringApplicationBuilder properties(String... defaultProperties);
public SpringApplicationBuilder properties(Properties defaultProperties);
public SpringApplicationBuilder properties(Map<String, Object> defaults);
public SpringApplicationBuilder profiles(String... profiles);
// Bean configuration
public SpringApplicationBuilder beanNameGenerator(BeanNameGenerator beanNameGenerator);
public SpringApplicationBuilder lazyInitialization(boolean lazyInitialization);
public SpringApplicationBuilder allowCircularReferences(boolean allowCircularReferences);
// Environment and resources
public SpringApplicationBuilder environment(ConfigurableEnvironment environment);
public SpringApplicationBuilder environmentPrefix(String environmentPrefix);
public SpringApplicationBuilder resourceLoader(ResourceLoader resourceLoader);
// Customization hooks
public SpringApplicationBuilder contextFactory(ApplicationContextFactory factory);
public SpringApplicationBuilder initializers(ApplicationContextInitializer<?>... initializers);
public SpringApplicationBuilder listeners(ApplicationListener<?>... listeners);
public SpringApplicationBuilder addBootstrapRegistryInitializer(BootstrapRegistryInitializer initializer);
public SpringApplicationBuilder applicationStartup(ApplicationStartup applicationStartup);
// Protected methods for subclassing
protected SpringApplication createSpringApplication(ResourceLoader resourceLoader, Class<?>... sources);
}import org.springframework.boot.Banner;
import org.springframework.boot.WebApplicationType;
import org.springframework.boot.builder.SpringApplicationBuilder;
public class MyApplication {
public static void main(String[] args) {
new SpringApplicationBuilder(MyApplication.class)
// Set web application type
.web(WebApplicationType.SERVLET) // SERVLET, REACTIVE, or NONE
// Configure banner
.bannerMode(Banner.Mode.OFF) // OFF, CONSOLE, or LOG
// Logging
.logStartupInfo(true)
// Headless mode
.headless(true)
// Register shutdown hook
.registerShutdownHook(true)
// Run
.run(args);
}
}import org.springframework.boot.builder.SpringApplicationBuilder;
public class MyApplication {
public static void main(String[] args) {
new SpringApplicationBuilder(MyApplication.class)
// Set default properties (string format)
.properties(
"server.port=8080",
"spring.application.name=my-app",
"logging.level.root=INFO"
)
// Set active profiles
.profiles("dev", "local")
// Add command-line properties
.addCommandLineProperties(true)
.run(args);
}
}Alternative property formats:
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;
// Using Map
Map<String, Object> props = new HashMap<>();
props.put("server.port", 8080);
props.put("spring.application.name", "my-app");
new SpringApplicationBuilder(MyApplication.class)
.properties(props)
.run(args);
// Using Properties
Properties props = new Properties();
props.setProperty("server.port", "8080");
props.setProperty("spring.application.name", "my-app");
new SpringApplicationBuilder(MyApplication.class)
.properties(props)
.run(args);Create parent-child context relationships for modular applications:
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
// Parent context configuration
@Configuration
class ParentConfig {
@Bean
public SharedService sharedService() {
return new SharedService();
}
}
// Child context configuration
@SpringBootApplication
class ChildConfig {
// Can access beans from parent context
}
public class HierarchicalApplication {
public static void main(String[] args) {
// Create parent-child hierarchy
new SpringApplicationBuilder(ParentConfig.class)
.web(WebApplicationType.NONE) // Parent typically non-web
.child(ChildConfig.class)
.web(WebApplicationType.SERVLET) // Child handles web requests
.run(args);
}
}Multiple children:
// Parent with two child contexts
SpringApplicationBuilder parent = new SpringApplicationBuilder(ParentConfig.class)
.web(WebApplicationType.NONE);
parent.child(WebConfig.class)
.web(WebApplicationType.SERVLET)
.properties("server.port=8080")
.run(args);
parent.child(AdminConfig.class)
.web(WebApplicationType.SERVLET)
.properties("server.port=8081")
.run(args);Create independent sibling contexts:
import org.springframework.boot.builder.SpringApplicationBuilder;
public class SiblingApplication {
public static void main(String[] args) {
// Main application
SpringApplicationBuilder main = new SpringApplicationBuilder(MainConfig.class)
.web(WebApplicationType.SERVLET)
.properties("server.port=8080");
// Create sibling context (independent)
main.sibling(AdminConfig.class)
.web(WebApplicationType.SERVLET)
.properties("server.port=9090")
.run(args);
// Run main context
main.run(args);
}
}import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.boot.bootstrap.BootstrapRegistryInitializer;
import org.springframework.context.ApplicationContextInitializer;
import org.springframework.context.ApplicationListener;
import org.springframework.boot.context.event.ApplicationReadyEvent;
public class CustomizedApplication {
public static void main(String[] args) {
new SpringApplicationBuilder(MyApplication.class)
// Bootstrap registry initializers
.addBootstrapRegistryInitializer(registry -> {
registry.register(MyService.class,
context -> new MyService());
})
// Application context initializers
.initializers(context -> {
System.out.println("Initializing context: " + context.getId());
})
// Event listeners
.listeners((ApplicationListener<ApplicationReadyEvent>) event -> {
System.out.println("Application ready!");
})
.run(args);
}
}import org.springframework.boot.ApplicationContextFactory;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.core.env.StandardEnvironment;
import org.springframework.core.metrics.ApplicationStartup;
import org.springframework.boot.context.metrics.buffering.BufferingApplicationStartup;
public class AdvancedApplication {
public static void main(String[] args) {
new SpringApplicationBuilder(MyApplication.class)
// Lazy initialization
.lazyInitialization(true)
// Allow circular references
.allowCircularReferences(false)
// Custom environment
.environment(new StandardEnvironment())
// Environment prefix
.environmentPrefix("myapp")
// Custom bean name generator
.beanNameGenerator((definition, registry) ->
"custom-" + definition.getBeanClassName())
// Application startup metrics
.applicationStartup(new BufferingApplicationStartup(2048))
.run(args);
}
}Complete production-ready application configuration:
import org.springframework.boot.Banner;
import org.springframework.boot.WebApplicationType;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.boot.context.metrics.buffering.BufferingApplicationStartup;
public class ProductionApplication {
public static void main(String[] args) {
new SpringApplicationBuilder(ProductionApplication.class)
// Application type
.web(WebApplicationType.SERVLET)
// Profiles
.profiles("prod")
// Properties
.properties(
"spring.application.name=my-service",
"server.port=8080",
"management.endpoints.web.exposure.include=health,metrics",
"logging.level.root=INFO"
)
// Logging
.logStartupInfo(true)
.bannerMode(Banner.Mode.LOG)
// Lifecycle
.registerShutdownHook(true)
// Performance
.lazyInitialization(false)
.applicationStartup(new BufferingApplicationStartup(4096))
// Security
.allowCircularReferences(false)
// Listeners
.listeners(event -> {
if (event instanceof org.springframework.boot.context.event.ApplicationFailedEvent) {
System.err.println("Application failed: " + event);
}
})
.run(args);
}
}Parent context with shared services and multiple child web contexts:
import org.springframework.boot.WebApplicationType;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
class SharedInfrastructure {
@Bean
public DataSource dataSource() {
return new DataSource();
}
@Bean
public CacheManager cacheManager() {
return new CacheManager();
}
}
@SpringBootApplication
class PublicApiService {
// Public-facing API
}
@SpringBootApplication
class AdminApiService {
// Admin API
}
public class MicroservicesPlatform {
public static void main(String[] args) {
// Shared infrastructure context
SpringApplicationBuilder parent = new SpringApplicationBuilder(SharedInfrastructure.class)
.web(WebApplicationType.NONE)
.properties(
"spring.datasource.url=jdbc:postgresql://localhost:5432/mydb"
);
// Public API service on port 8080
parent.child(PublicApiService.class)
.web(WebApplicationType.SERVLET)
.properties(
"server.port=8080",
"spring.application.name=public-api"
)
.profiles("public")
.run(args);
// Admin API service on port 9090
parent.child(AdminApiService.class)
.web(WebApplicationType.SERVLET)
.properties(
"server.port=9090",
"spring.application.name=admin-api"
)
.profiles("admin")
.run(args);
}
}Configure application differently based on environment:
import org.springframework.boot.Banner;
import org.springframework.boot.WebApplicationType;
import org.springframework.boot.builder.SpringApplicationBuilder;
public class EnvironmentAwareApplication {
public static void main(String[] args) {
String environment = System.getenv("APP_ENV");
boolean isProduction = "production".equals(environment);
SpringApplicationBuilder builder = new SpringApplicationBuilder(MyApplication.class)
.web(WebApplicationType.SERVLET);
if (isProduction) {
// Production configuration
builder
.profiles("prod")
.bannerMode(Banner.Mode.OFF)
.logStartupInfo(true)
.lazyInitialization(false)
.allowCircularReferences(false)
.properties(
"logging.level.root=WARN",
"server.tomcat.threads.max=200"
);
} else {
// Development configuration
builder
.profiles("dev")
.bannerMode(Banner.Mode.CONSOLE)
.logStartupInfo(true)
.lazyInitialization(true)
.properties(
"logging.level.root=DEBUG",
"spring.devtools.restart.enabled=true"
);
}
builder.run(args);
}
}Build applications for integration tests:
import org.springframework.boot.WebApplicationType;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.context.ConfigurableApplicationContext;
import org.junit.jupiter.api.Test;
public class IntegrationTest {
@Test
void testApplication() {
ConfigurableApplicationContext context = new SpringApplicationBuilder(TestConfig.class)
.web(WebApplicationType.NONE)
.profiles("test")
.properties(
"spring.datasource.url=jdbc:h2:mem:testdb",
"logging.level.root=DEBUG"
)
.registerShutdownHook(false) // Manually control lifecycle
.run();
try {
// Perform tests
MyService service = context.getBean(MyService.class);
// Test service
} finally {
context.close();
}
}
}Problem: Attempting to reuse builder for multiple applications.
Solution:
// WRONG - builder state is reused
SpringApplicationBuilder builder = new SpringApplicationBuilder(MyApp.class);
builder.web(WebApplicationType.SERVLET).run(args);
builder.web(WebApplicationType.REACTIVE).run(args); // Unexpected behavior
// CORRECT - create new builder for each application
new SpringApplicationBuilder(ServletApp.class)
.web(WebApplicationType.SERVLET)
.run(args);
new SpringApplicationBuilder(ReactiveApp.class)
.web(WebApplicationType.REACTIVE)
.run(args);Problem: Making parent context a web application causes port conflicts.
Solution:
// WRONG - parent context tries to start web server
new SpringApplicationBuilder(ParentConfig.class)
.web(WebApplicationType.SERVLET) // Will try to bind to port!
.child(ChildConfig.class)
.run(args);
// CORRECT - parent should be non-web
new SpringApplicationBuilder(ParentConfig.class)
.web(WebApplicationType.NONE) // No web server
.child(ChildConfig.class)
.web(WebApplicationType.SERVLET) // Child handles web
.run(args);Problem: Sibling contexts both try to bind to default port 8080.
Solution:
// WRONG - both contexts use port 8080
main.sibling(AdminConfig.class)
.web(WebApplicationType.SERVLET)
.run(args); // Port conflict!
// CORRECT - configure different ports
main.sibling(AdminConfig.class)
.web(WebApplicationType.SERVLET)
.properties("server.port=9090")
.run(args);Problem: Assuming child contexts inherit all parent properties.
Solution:
// Properties don't automatically inherit to children
SpringApplicationBuilder parent = new SpringApplicationBuilder(ParentConfig.class)
.properties("my.property=value"); // NOT inherited
// Explicitly set properties on child if needed
parent.child(ChildConfig.class)
.properties("my.property=value") // Must explicitly set
.run(args);package org.springframework.boot.builder;
import org.springframework.context.ApplicationContextInitializer;
import org.springframework.context.ConfigurableApplicationContext;
/**
* ApplicationContextInitializer for setting parent context.
* @since 1.0.0
*/
public class ParentContextApplicationContextInitializer
implements ApplicationContextInitializer<ConfigurableApplicationContext> {
public ParentContextApplicationContextInitializer(ConfigurableApplicationContext parent);
@Override
public void initialize(ConfigurableApplicationContext applicationContext);
/**
* Event published when parent context becomes available.
*/
public static class ParentContextAvailableEvent extends ApplicationEvent {
public ParentContextAvailableEvent(ConfigurableApplicationContext applicationContext,
ApplicationContext parentContext);
public ApplicationContext getParentContext();
}
}Listener that automatically closes a child application context when its parent context is closed. This class ensures proper cleanup in context hierarchies by propagating close events down the hierarchy tree.
package org.springframework.boot.builder;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.ApplicationListener;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.event.ContextClosedEvent;
import org.springframework.core.Ordered;
import org.springframework.boot.builder.ParentContextApplicationContextInitializer.ParentContextAvailableEvent;
/**
* Listener that closes the application context if its parent is closed.
* It listens for refresh events and grabs the current context from there,
* and then listens for closed events and propagates it down the hierarchy.
*
* @since 1.0.0
*/
public class ParentContextCloserApplicationListener
implements ApplicationListener<ParentContextAvailableEvent>,
ApplicationContextAware,
Ordered {
/**
* Get the order value of this listener.
* Returns Ordered.LOWEST_PRECEDENCE - 10
*
* @return the order value
*/
@Override
public int getOrder();
/**
* Set the ApplicationContext that this object runs in.
*
* @param context the ApplicationContext object to be used by this object
* @throws org.springframework.beans.BeansException if thrown by application context methods
*/
@Override
public void setApplicationContext(ApplicationContext context)
throws org.springframework.beans.BeansException;
/**
* Handle a ParentContextAvailableEvent.
* Installs a listener in the parent context to close the child when parent closes.
*
* @param event the event to respond to
*/
@Override
public void onApplicationEvent(ParentContextAvailableEvent event);
/**
* Subclasses may override to create their own subclass of ContextCloserListener.
* This still enforces the use of a weak reference.
*
* @param child the child context
* @return the ContextCloserListener to use
*/
protected ContextCloserListener createContextCloserListener(
ConfigurableApplicationContext child);
/**
* ApplicationListener to close the context when parent closes.
*/
protected static class ContextCloserListener
implements ApplicationListener<ContextClosedEvent> {
/**
* Create a new ContextCloserListener.
*
* @param childContext the child context to close when parent closes
*/
public ContextCloserListener(ConfigurableApplicationContext childContext);
/**
* Handle a ContextClosedEvent from the parent context.
* Closes the child context if the parent is closing.
*
* @param event the event to respond to
*/
@Override
public void onApplicationEvent(ContextClosedEvent event);
@Override
public boolean equals(Object obj);
@Override
public int hashCode();
}
}LOWEST_PRECEDENCE - 10 for proper sequencingContextCloserListener creationParentContextAvailableEvent is fired, it detects the parent contextContextCloserListener in the parent contextThis listener is typically used automatically by SpringApplicationBuilder when building context hierarchies:
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.context.ConfigurableApplicationContext;
@SpringBootApplication
public class HierarchyApplication {
public static void main(String[] args) {
ConfigurableApplicationContext parentContext = new SpringApplicationBuilder()
.sources(ParentConfig.class)
.run(args);
// Child context automatically gets ParentContextCloserApplicationListener
ConfigurableApplicationContext childContext = new SpringApplicationBuilder()
.sources(ChildConfig.class)
.parent(parentContext) // This triggers automatic listener registration
.run(args);
// When parent closes, child will automatically close too
parentContext.close();
// childContext is now also closed
}
}You can also register the listener manually if needed:
import org.springframework.boot.builder.ParentContextCloserApplicationListener;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
public class ManualRegistrationExample {
public static void main(String[] args) {
// Create parent context
ConfigurableApplicationContext parent =
new AnnotationConfigApplicationContext(ParentConfig.class);
// Create child context
ConfigurableApplicationContext child =
new AnnotationConfigApplicationContext();
child.setParent(parent);
// Manually register the closer listener
ParentContextCloserApplicationListener listener =
new ParentContextCloserApplicationListener();
child.addApplicationListener(listener);
listener.setApplicationContext(child);
// Register child context
child.register(ChildConfig.class);
child.refresh();
// Trigger parent context available event
child.publishEvent(new ParentContextApplicationContextInitializer
.ParentContextAvailableEvent(child, parent));
// Now when parent closes, child will automatically close
parent.close();
}
}You can extend the listener to customize close behavior:
import org.springframework.boot.builder.ParentContextCloserApplicationListener;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.event.ContextClosedEvent;
public class CustomParentContextCloserListener
extends ParentContextCloserApplicationListener {
@Override
protected ContextCloserListener createContextCloserListener(
ConfigurableApplicationContext child) {
return new CustomContextCloserListener(child);
}
protected static class CustomContextCloserListener extends ContextCloserListener {
public CustomContextCloserListener(ConfigurableApplicationContext childContext) {
super(childContext);
}
@Override
public void onApplicationEvent(ContextClosedEvent event) {
// Custom logic before closing
System.out.println("Parent context closing, performing cleanup...");
// Log context hierarchy information
ConfigurableApplicationContext context = getChildContext();
if (context != null) {
System.out.println("Closing child context: " +
context.getDisplayName());
}
// Call parent implementation to actually close the context
super.onApplicationEvent(event);
// Custom logic after closing
System.out.println("Child context closed successfully");
}
private ConfigurableApplicationContext getChildContext() {
// Access to childContext field through reflection if needed
// In practice, you might track this separately
return null;
}
}
}The ContextCloserListener uses WeakReference to hold the child context:
// Internal implementation detail:
// WeakReference allows child to be garbage collected
// even if parent still exists
public class ContextCloserListener {
private final WeakReference<ConfigurableApplicationContext> childContext;
public ContextCloserListener(ConfigurableApplicationContext childContext) {
// Stores weak reference, not strong reference
this.childContext = new WeakReference<>(childContext);
}
public void onApplicationEvent(ContextClosedEvent event) {
ConfigurableApplicationContext context = this.childContext.get();
// If context was garbage collected, get() returns null
if (context != null && context.isActive()) {
context.close();
}
}
}When using SpringApplicationBuilder.parent(), this listener is automatically registered:
import org.springframework.boot.builder.SpringApplicationBuilder;
// Parent context
SpringApplicationBuilder parentBuilder = new SpringApplicationBuilder()
.sources(ParentConfig.class);
ConfigurableApplicationContext parent = parentBuilder.run(args);
// Child context - ParentContextCloserApplicationListener is automatically added
SpringApplicationBuilder childBuilder = new SpringApplicationBuilder()
.sources(ChildConfig.class)
.parent(parent); // Triggers automatic listener registration
ConfigurableApplicationContext child = childBuilder.run(args);
// Automatic cleanup: closing parent will close child
parent.close();import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.boot.builder.ParentContextApplicationContextInitializer;