Interview Preparation J2EE & Spring, Spring Boot - Yash-777/MyWorld GitHub Wiki
| Uniform Resource Locators (URLs) | The Hypertext Transfer Protocol (HTTP) is designed to enable communications between clients and servers |
|---|---|
|
A URL (Uniform Resource Locator) is the address of a unique resource on the internet. It is one of the key mechanisms used by browsers to retrieve published resources, such as HTML pages, CSS documents, images, and so on.
The Web Storage API extends the Window object with two new properties β Document.cookie The Document property cookie lets you read and write cookies associated with the document. It serves as a getter and setter for the actual values of the cookies. localStorage.setItem('colorSetting', '#a4509b');
document.cookie = "yummy_cookie=choco"; |
The HTTP/1.0 specification defined the GET, HEAD and POST methods and the HTTP/1.1 specification added five new methods: OPTIONS, PUT, DELETE, TRACE and CONNECT.
π Example @RequestMapping(value = "/user/{id}", method = RequestMethod.GET)
public ResponseEntity getUser(@PathVariable Long id) {
return Optional
.ofNullable( userRepository.findOne(id) )
.map( user -> ResponseEntity.ok().body(user) ) //200 OK
.orElseGet( () -> ResponseEntity.notFound().build() ); //404 Not found
} |
HTTP Request & Response (Object Marshalling, unmarshalling)? In HTTP communication, marshalling converts Java objects to JSON/XML for requests, and unmarshalling converts responses back to Java objects.
Is marshalling the same as serialization? Serialization is Java-specific; marshalling is broader and used in HTTP, REST, and RPC.
Servlet lifecycle methods (init, service, destroy, getservletconfig, getservlet)
public abstract interface Servlet {
public abstract void init(ServletConfig paramServletConfig) throws ServletException;
public abstract ServletConfig getServletConfig();
public abstract void service(ServletRequest paramServletRequest, ServletResponse paramServletResponse)
throws ServletException, IOException;
public abstract String getServletInfo();
public abstract void destroy();
}By default, a web server (or servlet container) creates only one instance of a servlet. When multiple requests arrive for that servlet, each request is processed by a separate thread.
These threads are managed by a thread pool provided by the servlet container (for example, Tomcat).
Call we call
destroy() inside service()Β« What will happen? Yes, we can call destroy() from the service() Β« It will execute the code inside destroy() method, but it will not dispose the servlet object. Servlet get instantiated, disposed by the container.
The servlet container creates a ServletRequest & ServletResponse objects and passes both as an arguments to the servlet's service method.
- To send binary data in a MIME body response, use the ServletOutputStream returned by getOutputStream.
- To send character data, use the PrintWriter object returned by getWriter.
DispatcherServlet is a Spring Framework component, not part of the standard Servlet API. It acts as the front controller in a Spring web application, meaning all incoming HTTP requests first go to the DispatcherServlet.
Using the Servlet API, the DispatcherServlet receives requests from the web container (like Tomcat) and then applies Springβs web features to process them. It is responsible for:
- Mapping URLs to controller methods
- Invoking the correct handler (@Controller, @RestController)
- Performing data binding and validation
- Handling exceptions centrally
- Resolving views and generating responses
Spring Framework: A massive, powerful toolbox (framework) used to build Java applications. It provides features like Dependency Injection (DI) and Inversion of Control (IoC), but it requires you to set everything up manually.
Spring Boot: An extension of Spring that makes it easy to create "stand-alone, production-grade" applications. It takes away the headache of manual configuration. (simplifying configuration is one of the key goals)
Spring Boot Starter Parent
Parent pom providing dependency and plugin management for applications built with Maven.
| Spring Framework (Control) | Spring Boot (Speed) |
|---|---|
| π Core framework for building Java applications | π Built on top of Spring |
| Requires manual configuration | Auto-configuration |
| Needs XML / Java config | Minimal configuration |
| No embedded server | Embedded server (Tomcat/Jetty) |
| More boilerplate code | Very less |
| Production-ready features (Actuator) | |
| Full control, but slower setup | Faster development |
Spring Boot simplifies Spring by providing auto-configuration, embedded servers, and faster application setup.
Bean: All the objects created by spring container and stores/manages by IOC is called Spring Bean
What is IoC (Inversion of Control)?
Inversion of Control is a design principle where the control of object creation and dependency management is shifted from the program to a container/framework.
π Instead of creating objects manually, Spring handles object creation and lifecycle. We only provide configuration information to Spring about how an object should be created and managed.
- If a bean has dependencies, Spring ensures those dependencies are created and injected first using @Autowired.
- If the dependency is marked as @Lazy, Spring injects a proxy and creates the actual object only when it is first used.
What are different types of containers in Spring? BeanFactory, ApplicationContext (@Autowired vs @Lazy)
What is the IoC Container?
The IoC container is the core of the Spring Framework. The Spring IoC container is responsible for creating, configuring, and managing the lifecycle of application objects, while injecting their dependencies to promote loose coupling. It is responsible for:
- Read configuration (XML / annotations / Java config)
- Create beans
- Resolve dependencies
- Inject dependencies
- Manage lifecycle
| Without IoC (tight coupling) | With IoC (loose coupling) |
|---|---|
class Car {
Engine engine = new Engine(); // tightly coupled
}
|
class Car {
Engine engine;
@Autowored // IOC Creates and Inject dependencies
Car(Engine engine) {
this.engine = engine;
}
}
|
There are basically two types of IOC Containers in Spring:
- BeanFactory Container: BeanFactory is like a factory class that contains a collection of beans. It instantiates the bean whenever asked for by clients.
- ApplicationContext Container: The ApplicationContext interface is built on top of the BeanFactory interface.
@Autowired and @Lazy are features of the ApplicationContext, not plain BeanFactory.
- BeanFactory is the basic IoC container
- ApplicationContext is a more advanced container built on top of BeanFactory
- Annotation-based dependency injection (like
@Autowired, @Lazy, @Component, etc.) is fully supported by ApplicationContext
@Autowired and @Lazy are not features of the core BeanFactory. They are supported by the ApplicationContext, which extends BeanFactory and provides annotation processing via BeanPostProcessors.
Eagerly injected using @Autowired
|
Lazily initialized using @Autowired @Lazy, where Spring injects a proxy and creates the actual bean only when it is accessed |
|---|---|
@Autowired
class Car {
Engine engine = new Engine(); // tightly coupled
}
|
@Lazy is used along with @Autowired, the dependency is not created immediately
class Car {
Engine engine;
@Autowored // IOC Creates and Inject dependencies
Car(Engine engine) {
this.engine = engine;
}
}
|
@Component
class A {
@Autowired
B b; // created before A
}
@Component
class C {
@Autowired @Lazy
A a; // proxy injected, real A created when used
}What are the bean scopes in Spring? singleton, prototype, request, session, global-session
There are five types of spring bean scopes:
- singleton - only one instance of the spring bean will be created for the spring container. This is the default spring bean scope. While using this scope, make sure bean doesnβt have shared instance variables otherwise it might lead to data inconsistency issues.
- prototype β A new instance will be created every time the bean is requested from the spring container.
- request β This is same as prototype scope, however itβs meant to be used for web applications. A new instance of the bean will be created for each HTTP request.
- session β A new bean will be created for each HTTP session by the container.
- global-session β This is used to create global session beans for Portlet applications.
Spring IoC bean scopes (object creation):
-
Singleton: Only one bean instance per Spring container.
bean.getBean()called by T1 and T2 returns the same object. -
Prototype: A new bean instance is created for each request.
bean.getBean()called by T1 and T2 returns different objects.
Common IoC Annotations
| Annotation | Purpose |
|---|---|
@Component |
Marks a class as a Spring bean |
@Service |
Business logic layer |
@Repository |
Data access layer |
@Controller / @RestController
|
Web layer |
@Autowired |
Inject dependencies |
@Configuration |
Configuration class |
@Bean |
Defines a bean |
π± Spring Bean Lifecycle Spring beans are instantiated and managed by the Spring IoC container. Beans are created by providing bean configuration metadata to the container. This configuration metadata can be provided using XML, annotations, or Java-based configuration.
Create β Inject β Aware β Before β Init β After β Use β Destroy
| Spring Bean Lifecycle πΉ Bean Creation & Initialization Phase | π diagram-style explanation |
|---|---|
|
1. Read Configuration Metadata: IoC container identifies the bean definition from XML, Java config, or annotations. 2. Bean Instantiation: The bean object is created using reflection. 3. Dependency Injection: Properties are populated via 4. Aware Interfaces Callbacks (if implemented):
5. ApplicationContext-Specific Aware Callbacks:
6. BeanPostProcessor β Before Initialization: 7. Initialization Callbacks: 8. BeanPostProcessor β After Initialization: 9. Bean is Ready to Use: ApplicationContext is fully initialized, and the bean is ready for use. πΉ Bean Destruction Phase (Container Shutdown): Executed only for singleton beans:
|
βββββββββββββββββββββββββββββββ
β 1. Read Bean Configuration β
ββββββββββββββββ¬βββββββββββββββ
β
βββββββββββββββββββββββββββββββ
β 2. Bean Instantiation β
β (new / reflection) β
ββββββββββββββββ¬βββββββββββββββ
β
βββββββββββββββββββββββββββββββ
β 3. Dependency Injection β
β (@Autowired, @Value) β
ββββββββββββββββ¬βββββββββββββββ
β
βββββββββββββββββββββββββββββββ
β 4. Aware Interfaces β
β BeanNameAware β
β BeanFactoryAware β
β ApplicationContextAware β
ββββββββββββββββ¬βββββββββββββββ
β
βββββββββββββββββββββββββββββββ
β 5. BeanPostProcessor β
β beforeInitialization() β
ββββββββββββββββ¬βββββββββββββββ
β
βββββββββββββββββββββββββββββββ
β 6. Initialization β
β @PostConstruct β
β afterPropertiesSet() β
β custom init-method β
ββββββββββββββββ¬βββββββββββββββ
β
βββββββββββββββββββββββββββββββ
β 7. BeanPostProcessor β
β afterInitialization() β
ββββββββββββββββ¬βββββββββββββββ
β
βββββββββββββββββββββββββββββββ
β 8. Bean Ready to Use β
ββββββββββββββββ¬βββββββββββββββ
β
(Container Shutdown)
β
βββββββββββββββββββββββββββββββ
β 9. Destruction Phase β
β @PreDestroy β
β DisposableBean.destroy() β
β custom destroy-method β
βββββββββββββββββββββββββββββββ
|
Single Java class that demonstrates all 8 stages of the Spring Bean Lifecycle
package com.example.lifecycle;
import jakarta.annotation.*;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.*;
import org.springframework.context.*;
import org.springframework.stereotype.Component;
@lombok.extern.slf4j.Slf4j @Component
public class BeanLifecycleDemo implements
BeanNameAware, BeanFactoryAware, ApplicationContextAware,
InitializingBean, DisposableBean, SmartInitializingSingleton {
{
// Why Not Use Instance Block?
// This runs immediately after constructor call, BEFORE dependencies are injected.
}
public BeanLifecycleDemo() {
log.info("1οΈβ£ Constructor called β Bean instance created");
}
@Override
public void setBeanName(String name) {
log.info("2οΈβ£ BeanNameAware β Bean name set: {}", name);
}
@Override
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
log.info("3οΈβ£ BeanFactoryAware β BeanFactory injected");
}
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
log.info("4οΈβ£ ApplicationContextAware β ApplicationContext injected");
}
@PostConstruct
public void postConstruct() {
log.info("5οΈβ£ @PostConstruct β Bean fully constructed and dependencies injected");
}
@Override
public void afterPropertiesSet() throws Exception {
log.info("6οΈβ£ InitializingBean β afterPropertiesSet() called");
}
@Override
public void afterSingletonsInstantiated() {
log.info("7οΈβ£ SmartInitializingSingleton β All singleton beans are now instantiated");
}
@PreDestroy
public void preDestroy() {
log.info("8οΈβ£ @PreDestroy β Pre-destroy method called before bean is destroyed");
}
@Override
public void destroy() throws Exception {
log.info("8οΈβ£ DisposableBean β destroy() method called during shutdown");
}
}What is Spring Boot Starter Parent?
In a typical Spring Boot project, spring-boot-starter-parent is used as the parent POM. It provides sensible defaults for dependency versions, plugin management, and build configuration, allowing you to avoid repetitive manual setup.
Using a parent POM enables centralized management across one or more child projects, including:
- Configuration β Java version and other project-wide properties
- Dependency Management β Consistent, centralized versions for dependencies
- Default Plugin Configuration β Preconfigured settings for commonly used Maven plugins
This helps ensure consistency, reduces boilerplate, and minimizes version conflicts across projects.
<properties>
<java.version>17</java.version>
<resource.delimiter>@</resource.delimiter>
<maven.compiler.release>${java.version}</maven.compiler.release>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<spring-boot.run.main-class>${start-class}</spring-boot.run.main-class>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
</dependencies>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<configuration>
<archive>
<manifest>
<mainClass>${start-class}</mainClass>
<addDefaultImplementationEntries>true</addDefaultImplementationEntries>
</manifest>
</archive>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<configuration>
<archive>
<manifest>
<mainClass>${start-class}</mainClass>
<addDefaultImplementationEntries>true</addDefaultImplementationEntries>
</manifest>
</archive>
</configuration>
</plugin>Whatβs happening here?
- No Java version specified β inherited
-
No dependency versions β managed by Spring Boot
Spring Boot ensures tested, compatible versions. [Spring Framework,Jackson,Tomcat,Hibernate,Logging (Logback, SLF4J)] -
No plugin config β auto-configured [
maven-compiler-plugin,maven-failsafe-plugin,maven-jar-plugin,maven-war-plugin]
So this works without extra setup: [mvn spring-boot:run,mvn package]
Thatβs the magic β¨
What is the purpose of Spring Boot DevTools, and how does it help developers?
Spring Boot DevTools improves developer productivity by enabling automatic application restart and live reload. With DevTools, changes in code or resources are reflected immediately without manually restarting the server.
Maven Dependency:
<!-- Boot LOG:
OptionalLiveReloadServer : LiveReload server is running on port 35729
LocalDevToolsAutoConfiguration$RestartingClassPathChangeChangedEventListener - Restarting due to 1 class path change (0 additions, 0 deletions, 1 modification)
-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>@Configuration(proxyBeanMethods = false)
@ConditionalOnInitializedRestarter
@EnableConfigurationProperties(DevToolsProperties.class)
public class LocalDevToolsAutoConfiguration {
// Local LiveReload configuration.
@Configuration(proxyBeanMethods = false)
@ConditionalOnProperty(prefix = "spring.devtools.livereload", name = "enabled", matchIfMissing = true)
static class LiveReloadConfiguration {
}
// Local Restart Configuration.
@Lazy(false)
@Configuration(proxyBeanMethods = false)
@ConditionalOnProperty(prefix = "spring.devtools.restart", name = "enabled", matchIfMissing = true)
static class RestartConfiguration {
}
}DevTools watches for changes β restarts the IoC container β all beans (auto-configured or custom) are reloaded without manual server restart.
Adding the
spring-boot-devtoolsdependency enables automatic restart of the embedded Tomcat on classpath changes, during which Spring Boot auto-configuration re-runs and the IoC container recreates all beans.
Adding the spring-boot-devtools dependency does not allow you to exclude auto-configuration defined in the main method. DevTools only restarts the application context; it does not change or bypass @SpringBootApplication or @EnableAutoConfiguration behavior.
DevTools restarts recreate the ApplicationContext, so auto-configuration always executes again.
[ Code / Classpath Change ]
β
βΌ
ββββββββββββββββββββββββββββ
β Spring Boot DevTools β
β - Detects change β
β - Triggers restart β
ββββββββββββββ¬ββββββββββββββ
βΌ
ββββββββββββββββββββββββββββ
β JVM Restart (partial) β
β - ApplicationContext β
β is closed β
ββββββββββββββ¬ββββββββββββββ
βΌ
ββββββββββββββββββββββββββββ
β @SpringBootApplication β
β (includes β
β @EnableAutoConfiguration)β
ββββββββββββββ¬ββββββββββββββ
βΌ
ββββββββββββββββββββββββββββ
β Auto-Configuration Runs β
β - Conditions re-evaluatedβ
β - Beans re-created β
ββββββββββββββ¬ββββββββββββββ
βΌ
ββββββββββββββββββββββββββββ
β IoC Container Ready β
β - Embedded Tomcat starts β
β - Beans available β
ββββββββββββββββββββββββββββπ Key Explanation (Short & Clear)
- DevTools does not keep the same ApplicationContext
- It closes and recreates the context on every restart
- Since @SpringBootApplication includes @EnableAutoConfiguration, auto-configuration always runs again
- All conditional checks (@ConditionalOnClass, @ConditionalOnBean, etc.) are re-evaluated
SpringBoot - Using the @SpringBootApplication Annotation
@SpringBootApplication annotation serves as the entry point for an application : This is a convenience annotation that is equivalent to declaring @SpringBootConfiguration, @EnableAutoConfiguration, and @ComponentScan. It enables auto-configuration, component scanning, and Java-based configuration in a single annotation.
| Annotation | Simple Definition | What it actually does |
|---|---|---|
@SpringBootConfigurationJava-based configuration - An alternative to Springβs standard @Configuration used to declares one or more @Bean methods |
The "Blueprint" - A configuration class for defining beans. | Tells Spring: "This class contains definitions for beans (objects) that our application needs to run." |
|
@EnableAutoConfiguration Spring Boot auto-configuration attempts to automatically configure your Spring application based on the jar dependencies that you have added. |
The "Mind Reader" - A trigger for auto-configuration based on project dependencies. | Tells Spring Boot to look at your pom.xml or classpath & properties and automatically set up things like databases or web servers based on the libraries it finds. |
|
@ComponentScan to automatically pick up all Spring components, including @Configuration classes. |
The "Search Party" - The starting point for component scanning. | Tells Spring to look through your packages to find your Controllers, Services, and Components so it can manage them. |
Spring Bootβs auto-configuration mechanism inspects the classpath and automatically configures required beans based on available dependencies. For example:
- If
spring-boot-starter-webis present, Spring Boot sets up DispatcherServlet, Tomcat, and other web-related configurations automatically. - If
spring-boot-starter-data-jpais included, it configures an EntityManagerFactory, DataSource, and TransactionManager. This eliminates most of the boilerplate and lets developers focus on business logic rather than infrastructure setup.
Source Code of Spring Boot - @SpringBootApplication Annotation
@Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME)
@Documented @Inherited
@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan(excludeFilters = { @Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class),
@Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) })
public @interface SpringBootApplication {
// Exclude specific auto-configuration classes/names such that they will never be applied.
@AliasFor(annotation = EnableAutoConfiguration.class)
Class<?>[] exclude() default {};
@AliasFor(annotation = EnableAutoConfiguration.class)
String[] excludeName() default {};
/**
* Base packages to scan for annotated components.
* Note: this setting is an alias for @ComponentScan only. It has no effect on @Entityscanning or Spring Data Repository scanning.
* For those you should add @EntityScan and @Enable...Repositories annotations.
*/
@AliasFor(annotation = ComponentScan.class, attribute = "basePackages")
String[] scanBasePackages() default {};
@AliasFor(annotation = ComponentScan.class, attribute = "basePackageClasses")
Class<?>[] scanBasePackageClasses() default {};
// The BeanNameGenerator class to be used for naming detected components within the Spring container.
@AliasFor(annotation = ComponentScan.class, attribute = "nameGenerator")
Class<? extends BeanNameGenerator> nameGenerator() default BeanNameGenerator.class;
/**
* Specify whether @Bean methods should get proxied in order to enforce
* bean lifecycle behavior, e.g. to return shared singleton bean instances even in
* case of direct {@code @Bean} method calls in user code. This feature requires
* method interception, implemented through a runtime-generated CGLIB subclass which
* comes with limitations such as the configuration class and its methods not being
* allowed to declare {@code final}.
*/
@AliasFor(annotation = Configuration.class)
boolean proxyBeanMethods() default true;
}A Simple Spring Boot Application : SpringApplication.run(MyApplication.class, args);
| Jar Deployment | War Deployment |
|---|---|
@SpringBootApplication
@ComponentScan(basePackages = "com.github.yash777.myworld") // Scans configuration classes of child modules
@ConditionalOnProperty(
value = "server.app.war.deployment",
havingValue = "NO",
matchIfMissing = false
)
public class MyApplication {
/**
* Standard Spring Boot entry point for launching the application with an embedded web server.
*
* @param args Command-line arguments passed to the application.
*/
public static void main(String[] args) {
SpringApplication.run(MyApplication.class, args);
String[] beanNames = ctx.getBeanDefinitionNames();
Arrays.sort(beanNames);
for (String beanName : beanNames) {
System.out.println(beanName);
}
}
} |
@SpringBootApplication
@ComponentScan(basePackages = "com.github.yash777.myworld")
@ConditionalOnProperty(
value = "server.app.war.deployment",
havingValue = "YES",
matchIfMissing = false
)
public class MyApplicationWarDeployment extends SpringBootServletInitializer implements CommandLineRunner {
public static void main(String[] args) {
SpringApplication app = new SpringApplication(MyApplicationWarDeployment.class);
Properties props = new Properties();
// Optional: Define any default properties here if needed.
app.setBannerMode(Mode.CONSOLE); // Show banner in the console
app.setDefaultProperties(props);
app.run(args);
}
/**
* This method is executed after the Spring application context is initialized.
* Use it to perform any post-startup logic or initialization.
*/
@Override
public void run(String... args) throws Exception {
// Post-startup logic can go here.
}
} |
What is
@EnableAutoConfiguration?
| At any point, you can start to define your own configuration to replace specific parts of the auto-configuration. | Respects user configuration: If you define a bean, Spring Boot backs off. |
|---|---|
π It tells Spring Boot to automatically configure beans based on:
|
@Bean
DataSource myDataSource() { ... } |
If you need to find out what auto-configuration is currently being applied, and why, start your application with the --debug switch. Doing so enables debug logs for a selection of core loggers and logs a conditions report to the console.
@EnableAutoConfiguration loads auto-config classes from metadata : DataSourceAutoConfiguration.class
@EnableAutoConfiguration loads auto-config classes from metadata
Depending on Spring Boot version:
-
Spring Boot β€ 2.xβMETA-INF/spring.factories -
Spring Boot β₯ 3.xβMETA-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
π DataSourceAutoConfiguration is listed in this file : spring-boot-autoconfigure-2.7.18.jar
META-INF/spring.factories β That is what @EnableAutoConfiguration reads.
# Auto Configure
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration,\META-INF/spring-autoconfigure-metadata.properties
org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration=
org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration.AutoConfigureBefore=org.springframework.boot.autoconfigure.sql.init.SqlInitializationAutoConfiguration
org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration.ConditionalOnClass=javax.sql.DataSource,org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseType
org.springframework.boot.autoconfigure.jdbc.DataSourceConfiguration$Dbcp2=
org.springframework.boot.autoconfigure.jdbc.DataSourceConfiguration$Dbcp2.ConditionalOnClass=org.apache.commons.dbcp2.BasicDataSource
org.springframework.boot.autoconfigure.jdbc.DataSourceConfiguration$Hikari=
org.springframework.boot.autoconfigure.jdbc.DataSourceConfiguration$Hikari.ConditionalOnClass=com.zaxxer.hikari.HikariDataSource
org.springframework.boot.autoconfigure.jdbc.DataSourceConfiguration$OracleUcp=
org.springframework.boot.autoconfigure.jdbc.DataSourceConfiguration$OracleUcp.ConditionalOnClass=oracle.jdbc.OracleConnection,oracle.ucp.jdbc.PoolDataSourceImpl
org.springframework.boot.autoconfigure.jdbc.DataSourceConfiguration$Tomcat=
org.springframework.boot.autoconfigure.jdbc.DataSourceConfiguration$Tomcat.ConditionalOnClass=org.apache.tomcat.jdbc.pool.DataSource
@SuppressWarnings("deprecation")
@Configuration(proxyBeanMethods = false)
@ConditionalOnClass({ DataSource.class, EmbeddedDatabaseType.class })
@ConditionalOnMissingBean(type = "io.r2dbc.spi.ConnectionFactory")
@AutoConfigureBefore(SqlInitializationAutoConfiguration.class)
@EnableConfigurationProperties(DataSourceProperties.class)
@Import({ DataSourcePoolMetadataProvidersConfiguration.class,
DataSourceInitializationConfiguration.InitializationSpecificCredentialsDataSourceInitializationConfiguration.class,
DataSourceInitializationConfiguration.SharedCredentialsDataSourceInitializationConfiguration.class })
public class DataSourceAutoConfiguration {
}
@ConfigurationProperties(prefix = "spring.datasource")
public class DataSourceProperties implements BeanClassLoaderAware, InitializingBean {
private ClassLoader classLoader;
// Datasource name to use if "generate-unique-name" is false. Defaults to "testdb" when using an embedded database, otherwise null.
private String name;
// Fully qualified name of the connection pool implementation to use. By default, it is auto-detected from the classpath.
private Class<? extends DataSource> type;
private String driverClassName;
private String url;
private String username;
private String password;
}Disabling Specific Auto-configuration Classes: If you find that specific auto-configuration classes that you do not want are being applied, you can use the exclude attribute of @SpringBootApplication to disable them, as shown in the following example:
// 1. Exclude in @SpringBootApplication (main class)
@SpringBootApplication(exclude = { DataSourceAutoConfiguration.class })
// 2. Exclude using @EnableAutoConfiguration
@EnableAutoConfiguration(exclude = DataSourceAutoConfiguration.class)
// 3. Exclude via application.properties
spring.autoconfigure.exclude=org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfigurationIf the class is not on the classpath, you can use the excludeName attribute of the annotation and specify the fully qualified name instead. If you prefer to use @EnableAutoConfiguration rather than @SpringBootApplication, exclude and excludeName are also available. Finally, you can also control the list of auto-configuration classes to exclude by using the spring.autoconfigure.exclude property.
Both JAX-RS and Spring REST support path and query parameters; JAX-RS uses @PathParam and @QueryParam, while Spring uses @PathVariable and @RequestParam, with similar URL semantics but different frameworks.
| JAX-RS (Jersey) β Java EE / Jakarta EE standard | Spring REST β Spring Framework |
|---|---|
package javax.ws.rs.*;
@GET
@Path("/orders/{id}")
public String getOrder(
@PathParam("id") String id,
@QueryParam("queryParamName") int i) {
return "Order ID: " + id;
}
|
package org.springframework.web.bind.annotation.*;
@GetMapping("/orders/{id}")
public String getOrder(
@PathVariable String id,
@RequestParam("queryParamName") int i) {
return "Order ID: " + id;
}
|
| Bean Ambiguity |
@PrimaryApplied on a bean definition (default bean) |
@QualifierApplied at the injection point (explicit bean selection) |
|---|---|---|
When multiple beans of the same type exist and Spring tries to inject by type, it cannot decide which one to choose.
@Component
class PaypalService implements PaymentService {}
@Component
class StripeService implements PaymentService {}
@Autowired
private PaymentService paymentService;
// β NoUniqueBeanDefinitionException: expected single matching bean but found 2 |
Marks one bean as the default choice when multiple beans of the same type exist.
@Component
@Primary
class PaypalService implements PaymentService {}
@Component
class StripeService implements PaymentService {}
@Autowired
private PaymentService paymentService; // PaypalService injected |
Explicitly tells Spring which bean to inject by name or qualifier value.
@Component("paypal")
class PaypalService implements PaymentService {}
@Component("stripe")
class StripeService implements PaymentService {}
@Autowired
@Qualifier("stripe")
private PaymentService paymentService; // StripeService injected |
When should we choose @Primary instead of @Qualifier in Spring applications?
Use @Primary when one implementation should act as the default most of the time. Use @Qualifier when you need explicit control over which bean is injected. In development, @Qualifier is preferred for clarity, while @Primary is convenient for rare or default cases.
@Primary = βdefault choice when no qualifier is specifiedβ
| Default implementation (used when no property or mysql) | The non-primary bean can still be used explicitly with `@Qualifier`. |
|---|---|
β If db.to.use is missing or set to mysql β DataRepository = MySqlRepository
@Component
@Primary
@ConditionalOnProperty(
name = "db.to.use",
havingValue = "mysql",
matchIfMissing = true
)
class MySqlRepository implements DataRepository {
}
|
β If db.to.use=graphdb β DataRepository = GraphDbRepository
@Component
@ConditionalOnProperty(name = "db.to.use", havingValue = "graphdb")
class GraphDbRepository implements DataRepository {
}
|
What are the differences between @Component, @Controller, @RestController, @Service, and @Repository in Spring, and how do they behave in different layers of an application?
Spring Stereotype Annotations
package org.springframework.stereotype;
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Indexed
public @interface Component {
String value() default "";
}Domain-Driven Design: Below annotation's serves as a specialization of
@Component
| Controller / RestController (Web Layer) | Service (Business Layer) | Repository (Data Access Layer) |
|---|---|---|
@Component
public @interface Controller {
@AliasFor(annotation = Component.class)
String value() default "";
}
@Controller + @ResponseBody automatically.- @RestController is a specialized controller for REST APIs where return values are automatically serialized to JSON. package org.springframework.web.bind.annotation;
@Controller @ResponseBody
public @interface RestController {
@AliasFor(annotation = Controller.class)
String value() default "";
}
|
@Service on interface β β No bean created
@Service on implementation classes β β
Beans are created and managed by Spring.
@Component
public @interface Service {
@AliasFor(annotation = Component.class)
String value() default "";
}
|
- @Repository on interface that extend JpaRepository β β
Bean created at runtime by Spring Data. - @Repository on implementation classes β β Beans are created and managed by Spring. - Adds exception translation (DataAccessException, PersistenceExceptionTranslationPostProcessor) for DAO layer. @Component
public @interface Repository {
@AliasFor(annotation = Component.class)
String value() default "";
}
|
Spring Boot Actuator wiki
Spring Boot Actuator provides production-ready endpoints to monitor and manage the health, metrics, and behavior of a running Spring Boot application.
Actuator = Monitor + Manage
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId> <!-- Required for HTTP exposure -->
</dependency>Common Actuator Endpoints and Its details, Why Actuator Can Be a Security Risk
| Endpoint | Purpose |
|---|---|
/actuator/health |
Application health (UP / DOWN) |
/actuator/info |
App information |
/actuator/metrics |
Performance metrics |
/actuator/env |
Environment properties |
/actuator/beans |
All Spring beans |
Request : http://localhost:8080/actuator/health
Response: { "status": "UP" }
Why Actuator is Important
- Used in production monitoring
- Integrates with monitoring tools (Prometheus, Grafana)
- Helps DevOps and support teams
- Useful for microservices health checks
Why Actuator Can Be a Security Risk
Spring Boot Actuator exposes internal application details.
If these endpoints are publicly accessible, attackers can gain sensitive information or even control parts of the application.
Spring Boot is secure by default:
- Only
/healthand/infoare exposed over HTTP - Other endpoints are disabled or protected
-
/shutdownis disabled by default
Best Practices to Secure Actuator π: Actuator endpoints can expose sensitive application data, so they must be restricted, secured, or disabled to prevent unauthorized access in production.
# Expose Only What You Need
management.endpoints.web.exposure.include=health,info
# Use Separate Port (Recommended)
management.server.port=9090
# Require authentication, Restrict access to admin roles only
management.endpoint.health.show-details=when_authorized
# Disable Dangerous Endpoints
management.endpoint.shutdown.enabled=false| Actuator Endpoint | Information Exposed | Security Risk |
|---|---|---|
/actuator/env |
Environment variables, config values | Leaks secrets like DB URLs, usernames, API keys |
/actuator/beans |
All Spring bean definitions | Reveals internal application structure |
/actuator/threaddump |
Thread execution details | Helps attackers analyze system behavior |
/actuator/heapdump |
JVM memory snapshot | Memory data leak, may expose sensitive data |
/actuator/shutdown |
Application control | Can stop the application remotely |
/actuator/mappings |
All request mappings | Reveals all available APIs |
Spring AOP wiki
Spring AOP (Aspect-Oriented Programming) allows you to modularize cross-cutting concernsβlike logging, security, or transactionsβseparately from your core business logic.
Spring AOP applies
cross-cutting logic to methods using proxies at runtime. π It adds extra behavior to methods without changing the actual code.
Important
π @EnableAutoConfiguration reacts mainly to Spring Boot starters, not plain Spring libraries.
spring-boot-starter-aop Spring Boot (Recommended) |
Adding spring-aspects only provides AOP APIs: @EnableAspectJAutoProxy is required to activate proxy-based AOP. |
|---|---|
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
|
To enable @AspectJ support with Java @Configuration add the @EnableAspectJAutoProxy annotation
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aspects</artifactId>
</dependency>
@Configuration
@EnableAspectJAutoProxy
public class AppConfig { }
|
Key components of Aspect-Oriented Programming (AOP):
| Concept | Code Representation | Explanation |
|---|---|---|
| Aspect |
@Aspect on LoggingAspect class |
A class that encapsulates advices and pointcuts (cross-cutting logic) |
| Join Point |
Parameter JoinPoint joinPoint in advice methods |
A point in execution like method call or exception throw
|
| Pointcut | @Pointcut("execution(...)") |
An expression that matches join points |
| Advice |
@Before, @After, @AfterReturning, @AfterThrowing, @Around
|
The actual code executed at the matched join point |