Spring Boot
Spring vs Spring Boot
Spring Framework and Spring Boot are not competing technologies — Spring Boot is built on top of Spring Framework. But they solve different problems and make different trade-offs. Understanding the distinction explains why Spring Boot exists and when you'd choose one over the other.
The Relationship — Spring Boot IS Spring
Spring Boot is not a replacement for Spring Framework. It's built entirely on top of Spring Framework and uses all the same underlying mechanisms: the IoC container, dependency injection, AOP, Spring MVC, Spring Data, Spring Security — all of it.
The difference is in how you configure and bootstrap those features. Spring Framework gives you the tools and leaves configuration entirely to you. Spring Boot provides opinionated defaults, auto-configuration, and starters that configure Spring Framework automatically based on what's on your classpath.
Think of it this way: Spring Framework is the engine. Spring Boot is the car — the engine with transmission, steering, dashboard, and all the parts assembled so you can drive immediately, rather than assembling it yourself.
Configuration — Manual vs Automatic
The most fundamental difference between Spring and Spring Boot is configuration. Spring requires you to declare everything explicitly. Spring Boot infers and configures automatically.
XML
// ── Spring Framework — manual configuration ────────────────────────
// 1. web.xml (required for servlet container):
<servlet>
<servlet-name>dispatcher</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>dispatcher</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
// 2. applicationContext.xml (Spring beans):
<context:component-scan base-package="com.example"/>
<bean id="dataSource" class="org.apache.commons.dbcp2.BasicDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost/mydb"/>
</bean>
<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="dataSource" ref="dataSource"/>
</bean>
<tx:annotation-driven/>
// 3. dispatcher-servlet.xml (MVC config):
<mvc:annotation-driven/>
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/views/"/>
<property name="suffix" value=".jsp"/>
</bean>
// ── Spring Boot — zero configuration ────────────────────────────────
@SpringBootApplication // one annotation replaces all of the above
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
// application.properties: spring.datasource.url=jdbc:mysql://localhost/mydb
// That's the equivalent of all the XML above.Dependency Management
Managing dependencies manually in Spring Framework is error-prone — version conflicts between Spring modules, Jackson, Hibernate, and other libraries cause hours of debugging. Spring Boot's parent POM solves this entirely.
XML
<!-- Spring Framework — manual version management: -->
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>6.0.11</version> <!-- must manually keep in sync -->
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>6.0.11</version> <!-- must match spring-core -->
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-orm</artifactId>
<version>6.0.11</version>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-core</artifactId>
<version>6.2.7.Final</version> <!-- must be compatible with Spring 6 -->
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.15.2</version> <!-- must be compatible -->
</dependency>
<!-- 10+ more... -->
</dependencies>
<!-- Spring Boot — parent POM manages ALL versions: -->
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.1.4</version>
</parent>
<dependencies>
<!-- One starter = all web dependencies at compatible versions: -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<!-- No version — inherited from parent -->
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
</dependencies>Deployment Model
Spring Framework applications are packaged as WAR files and deployed to an external application server. Spring Boot applications are self-contained JARs with an embedded server.
Java
// ── Spring Framework deployment ─────────────────────────────────
// 1. Package as WAR: mvn package → myapp.war
// 2. Install Tomcat: download, configure, start
// 3. Deploy WAR: copy myapp.war to tomcat/webapps/
// 4. Tomcat URL: http://localhost:8080/myapp/
// Drawbacks:
// - Must install and configure external server
// - Tomcat/server version must be managed separately
// - Context path in URL (/myapp) unless configured otherwise
// - WAR deployment means Tomcat classpath and app classpath interaction
// ── Spring Boot deployment ───────────────────────────────────────
// 1. Package as JAR: mvn package → myapp.jar (fat JAR ~30MB)
// 2. Run: java -jar myapp.jar
// 3. URL: http://localhost:8080/
// Benefits:
// - No external server installation
// - Server version is a Maven dependency — controlled by you
// - Identical artifact runs in dev, staging, production
// - Works perfectly in Docker containers
// - Cloud-native by default (Kubernetes, Cloud Foundry, AWS)
// Spring Boot can still produce a WAR for legacy server deployment:
@SpringBootApplication
public class Application extends SpringBootServletInitializer {
@Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder builder) {
return builder.sources(Application.class);
}
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
// pom.xml: <packaging>war</packaging>Feature Comparison at a Glance
A direct side-by-side comparison of the key differences:
Java
// Feature Spring Framework Spring Boot
// ──────────────────────────────────────────────────────────────────
// Configuration Manual XML or Java config Auto-configured by classpath
// Dependencies Manual, version conflicts Starters + parent POM
// Server External (Tomcat, JBoss) Embedded (Tomcat/Jetty/Undertow)
// Packaging WAR JAR (fat JAR)
// Startup code Extensive boilerplate @SpringBootApplication + main()
// Properties Multiple config files Single application.properties
// Testing Requires more setup @SpringBootTest, @WebMvcTest
// Monitoring Manual setup Actuator included
// Learning curve Steep Gentle
// Flexibility Maximum — everything manual Opinionated — override when needed
// Use case Legacy systems, fine-tuned control New projects, microservices
// When to use Spring Framework directly:
// - Migrating a legacy XML-configured Spring application
// - Need granular control over every configuration detail
// - Building a library or framework, not an application
// When to use Spring Boot:
// - Starting a new project (always)
// - Building microservices
// - REST APIs
// - Batch processing
// - Event-driven applications
// Basically: new projects should always start with Spring BootSame Code, Different Bootstrap
The business logic code is identical between Spring and Spring Boot. The difference is only in bootstrapping. A service, repository, or controller written for Spring MVC works unchanged in Spring Boot.
Java
// This code is IDENTICAL whether you use Spring or Spring Boot:
@Service
@Transactional
public class UserService {
private final UserRepository repository;
public UserService(UserRepository repository) {
this.repository = repository;
}
public User createUser(CreateUserRequest request) {
if (repository.existsByEmail(request.email())) {
throw new DuplicateEmailException(request.email());
}
return repository.save(new User(request.email(), request.name()));
}
}
@RestController
@RequestMapping("/users")
public class UserController {
private final UserService userService;
public UserController(UserService userService) {
this.userService = userService;
}
@PostMapping
@ResponseStatus(HttpStatus.CREATED)
public User createUser(@RequestBody @Valid CreateUserRequest request) {
return userService.createUser(request);
}
}
// The ONLY difference between Spring and Spring Boot is in:
// 1. The bootstrap class (how the application starts)
// 2. The pom.xml (starters vs manual dependencies)
// 3. The absence of XML configuration files in Spring Boot
// Your actual application logic: zero changes.