1. What is IoC (Inversion of Control) or Dependency Injection?
Inversion of Control (IoC) is a design principle where control of object creation and binding is shifted from the application code to a container/framework. In Dependency Injection (DI), this is done by externally injecting dependencies (objects) into a class rather than the class creating them itself.
-
Example: Instead of
new Service()
, you declare aService
field and let the Spring container inject the instance. -
Benefits:
-
Decouples class dependencies.
-
Improves maintainability and testability.
✅ What is Dependency Injection (DI)?
Dependency Injection is a specific implementation technique of IoC. It is a pattern where dependencies (objects that a class needs to perform its work) are "injected" into the class, instead of the class creating them directly.
Think of IoC as the general concept, and DI as one of the ways to achieve it.
✅ Types of Dependency Injection in Spring:
-
Constructor Injection
-
Setter Injection
-
Field Injection (not recommended for testing)
✅ Example Without DI (Tight Coupling):
public class StudentService {
private StudentRepository repository = new StudentRepository(); // tightly coupled
public void register() {
repository.save();
}
}
-
The
StudentService
class creates theStudentRepository
on its own usingnew
. -
Hard to test and maintain.
✅ Same Example With DI (Loose Coupling using IoC):
Step 1: Define the Repository
@Repository
public class StudentRepository {
public void save() {
System.out.println("Student saved!");
}
}
Step 2: Inject the Repository into the Service
@Component
public class StudentService {
private final StudentRepository repository;
@Autowired
public StudentService(StudentRepository repository) {
this.repository = repository;
}
public void register() {
repository.save();
}
}
-
Here,
StudentRepository
is injected by the Spring IoC container. -
The class does not manage the creation of its dependency.
✅ Spring Boot Main Class
@SpringBootApplication
public class MyApp {
public static void main(String[] args) {
ApplicationContext context = SpringApplication.run(MyApp.class, args);
StudentService service = context.getBean(StudentService.class);
service.register();
}
}
✅2. Types of Dependency Injection
Spring supports:
-
Constructor Injection
-
Setter Injection
Other frameworks (like Avalon) also support Interface Injection, but Spring does not.
a. Constructor Injection
@Component
public class BookService {
private final BookRepository repository;
@Autowired
public BookService(BookRepository repository) {
this.repository = repository;
}
}
b. Setter Injection
@Component
public class BookService {
private BookRepository repository;
@Autowired
public void setBookRepository(BookRepository repository) {
this.repository = repository;
}
}
3. Benefits of IoC (Dependency Injection)
-
Less boilerplate code: We don’t need to write factory or singleton code to manage dependencies.
-
Improved testability: Dependencies can be easily mocked.
-
Loose Coupling: Components are independent of how their dependencies are constructed.
-
Lifecycle and scope control: Spring manages object scopes (singleton, prototype, etc.).
-
Support for AOP: Cross-cutting concerns like logging, security can be injected.
4. What is Spring Framework?
Spring is a lightweight, open-source Java framework for building enterprise-grade applications. It provides a comprehensive infrastructure support for developing Java applications.
Advantages:
-
Modular & Layered Architecture.
-
Promotes Plain Old Java Object (POJO) programming.
-
Reduces boilerplate code through IoC/DI.
-
Open-source and vendor-neutral.
5. Features of Spring
Feature | Description |
---|---|
Lightweight | Minimal memory and processing overhead. |
IoC | Dependencies are injected into components. |
AOP (Aspect-Oriented Programming) | Separates cross-cutting concerns like logging/security. |
Container | Manages object lifecycle and configuration. |
Spring MVC | Powerful and extensible web MVC framework. |
Transaction Management | Abstracts transactions across databases and APIs. |
JDBC Exception Handling | Simplifies JDBC error handling via custom exception hierarchy. |
ORM Integration | Seamlessly integrates with Hibernate, JPA, etc. |
6. Spring MVC Example
@Controllerpublic class GreetingController {
@GetMapping("/greet")
public String greet(Model model) {
model.addAttribute("message", "Hello from Spring MVC!");
return "greeting"; // returns greeting.jsp or other view
}
}
7. JDBC Exception Handling
Spring provides a cleaner way of dealing with exceptions:
@Repositorypublic class UserDao {
@Autowired
private JdbcTemplate jdbcTemplate;
public void addUser(User user) {
try {
jdbcTemplate.update("INSERT INTO users(name) VALUES (?)", user.getName());
} catch (DataAccessException e) {
// Handle Spring’s wrapped exception instead of raw SQLException
throw new RuntimeException("Database error: " + e.getMessage());
}
}
}
8. Types of Dependency Injection Spring Supports
-
Constructor Injection: Preferred when dependencies are mandatory.
-
Setter Injection: Preferred when dependencies are optional.
Example of Constructor Injection:
@Service
public class OrderService {
private final OrderRepository repository;
@Autowired
public OrderService(OrderRepository repository) {
this.repository = repository;
}
}
Example of Setter Injection:
@Service
public class OrderService {
private OrderRepository repository;
@Autowired
public void setRepository(OrderRepository repository) {
this.repository = repository;
}
}
9. What is BeanFactory?
BeanFactory is the simplest Spring IoC container. It lazily loads beans and manages their lifecycle.
Core Interfaces:
-
BeanFactory
is the root interface. -
Implemented by classes like
XmlBeanFactory
.
Why prefer ApplicationContext?
-
Supports internationalization (i18n)
-
Publishes events to listeners
-
Resolves file resources
-
Autowires annotations like
@Autowired
,@Component
Example:
BeanFactory factory = new XmlBeanFactory(new ClassPathResource("beans.xml"));
Student student = (Student) factory.getBean("student");
10.What is the difference between BeanFactory and ApplicationContext?BeanFactory and ApplicationContext are Spring IoC containers responsible for managing beans.
However, ApplicationContext provides a more advanced and feature-rich implementation
compared to BeanFactory.
Key Differences:
- Message Resolution (i18n):
ApplicationContext provides an internationalization (i18n) mechanism to
resolve text messages using properties files, which BeanFactory does not.
- Resource Loading:
It supports a generic way to access file resources like images, properties
files, etc., using the Resource interface. For example, loading file:/some/path/file.txt or classpath:config.xml.
- Event Propagation:
ApplicationContext can publish application events to beans registered as ApplicationListener. This is part of the observer pattern for event-driven apps.
- Declarative Operations:
You can handle things like autowiring, property injection, and lifecycle callbacks declaratively (via XML or annotations) in ApplicationContext. These must be manually handled in BeanFactory.
- Built-in Support for BeanPostProcessors and BeanFactoryPostProcessors:
These are automatically detected and registered in ApplicationContext but require manual registration in BeanFactory.
- Interfaces Implemented:
- ApplicationContext implements ResourceLoader, MessageSource, ApplicationEventPublisher, and BeanFactory.
- BeanFactory is a basic container providing only getBean() and dependency resolution.
11. What are the common implementations of the ApplicationContext?
Spring provides several implementations of ApplicationContext, used depending on the environment:
1. ClassPathXmlApplicationContext:
o Loads configuration XML from the classpath.
o Common in standalone apps.
Example:
ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
2. FileSystemXmlApplicationContext:
o Loads the context definition from an XML file in the file system.
o Useful when the config is outside the classpath.
Example:
ApplicationContext context = new FileSystemXmlApplicationContext("C:/config/beans.xml");
3. XmlWebApplicationContext:
o Specialized for web applications.
o Automatically initialized by the Spring Web module (via ContextLoaderListener).
________________________________________
12. How does a typical Spring implementation look like?
A complete Spring application typically includes:
1. Interface: Defines the contract for the service.
2. Implementation Class: Implements the interface, uses Spring DI for its dependencies.
3. Spring AOP (optional): Adds cross-cutting concerns like logging, security, or transactions.
4. Configuration File (XML or Java): Defines the beans, wiring, scopes, etc.
5. Client Code: Retrieves the bean from Spring and calls the required methods.
________________________________________
13. What is the typical bean lifecycle in Spring BeanFactory Container?
The following steps describe how Spring manages the bean lifecycle:
1. Bean Instantiation: Bean definitions are read from XML or Java config and objects are instantiated.
2. Dependency Injection: All defined properties (via setters or constructor) are injected.
3. BeanNameAware: If implemented, Spring calls setBeanName() with the bean’s ID.
4. BeanFactoryAware: If implemented, Spring injects the BeanFactory into the bean.
5. BeanPostProcessor (Before): Any registered BeanPostProcessor's postProcessBeforeInitialization() method is called.
6. Custom init-method: If configured, Spring calls the custom init method (defined using init-method).
7. BeanPostProcessor (After): Calls postProcessAfterInitialization() from BeanPostProcessor.
________________________________________
14. What do you mean by Bean wiring?
Bean wiring is the process of defining how beans are connected or injected with dependencies in the Spring container.
Autowiring Modes:
1. no (default): No autowiring; dependencies must be explicitly defined.
2. byName: Spring injects a bean whose name matches the property name.
3. byType: Spring injects a bean whose type matches the property type.
4. constructor: Uses the constructor with matching arguments.
5. autodetect (deprecated): Chooses between constructor and byType using reflection.
________________________________________
15. What ORM frameworks does Spring support?
Spring supports integration with multiple ORM frameworks:
• Hibernate
• iBatis / MyBatis
• JPA (Java Persistence API)
• TopLink (now EclipseLink)
• JDO (Java Data Objects)
• OJB (ObJectRelationalBridge)
________________________________________
16. What are the ways to access Hibernate using Spring?
Two common approaches:
1. Using HibernateTemplate and Callback API:
o Simplifies repetitive boilerplate Hibernate code (session management, transactions).
o E.g., hibernateTemplate.save(entity);
2. Extending HibernateDaoSupport:
o Inherit this class to gain access to HibernateTemplate and use methods directly.
3. With AOP-based Transaction Management:
o Declarative transactions using Spring’s @Transactional.
________________________________________
17. How to integrate Spring and Hibernate using HibernateDaoSupport?
Steps:
1. Configure LocalSessionFactoryBean in Spring:
Inject database properties, mapping files, etc.
2. DAO Implementation Extends HibernateDaoSupport:
This gives access to getHibernateTemplate() for CRUD operations.
3. Wire Transaction Support using AOP:
Use XML or @Transactional to define transaction boundaries.
________________________________________
18. What are the Bean Scopes in Spring Framework?
Scope Description
singleton Single instance per Spring container. Shared and reused. (Default)
prototype A new instance is created every time it is requested.
request One instance per HTTP request. Only available in web applications.
session One instance per HTTP session. Used in web applications.
globalSession Like session but shared across all portlets in a web app (Portlet context only).
________________________________________
19. What is AOP (Aspect-Oriented Programming)?
AOP is a programming paradigm that allows separation of cross-cutting concerns (like logging, security, and transaction management) from core business logic.
• Aspect: Module for cross-cutting concern.
• Join Point: Specific point in execution (e.g., method execution).
• Advice: Code to execute at a join point (before, after, around).
________________________________________
20. How is AOP used in Spring?
Spring uses AOP to provide declarative enterprise services, such as:
• Transaction Management (@Transactional)
• Security (@PreAuthorize)
• Logging, Auditing, etc.
Developers can also define custom aspects using @Aspect.
________________________________________
21. What is an Aspect?
An aspect is a module that encapsulates behaviors that cut across multiple classes.
Examples:
• Logging aspect
• Security aspect
• Transaction aspect
Spring supports two types:
• XML-based AOP
• Annotation-based (@Aspect)
________________________________________
22. What is a JoinPoint?
A join point is a specific point during program execution, such as:
• Method execution
• Exception handling
• Constructor invocation
Spring AOP supports only method execution join points.
________________________________________
23. What is Advice?
Advice is the actual action taken at a join point. Types include:
• Before Advice: Runs before the method.
• After Advice: Runs after the method completes.
• After Returning: Runs if method completes successfully.
• After Throwing: Runs if method throws an exception.
• Around Advice: Surrounds the method call, giving full control.
In Spring, advice is implemented as methods inside an aspect class.
24. ✅ RestTemplate in Java (Spring Framework)
RestTemplate is a synchronous HTTP client provided by Spring for consuming RESTful web services. It's part of the spring-web module.
๐ Note: As of Spring 5, RestTemplate is in maintenance mode. It is still widely used, but WebClient (from Spring WebFlux) is now the recommended alternative for new applications due to its non-blocking nature.
๐น When to use RestTemplate:
Use it when:
You want to make HTTP requests (GET, POST, PUT, DELETE, etc.)
The communication is synchronous (blocking).
You are consuming REST APIs in a Spring Boot or Spring MVC application.
๐ง Add Maven Dependency
xml
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
</dependency>
๐ ️ How to Create a RestTemplate Bean
java
@Configuration
public class RestTemplateConfig {
@Bean
public RestTemplate restTemplate() {
return new RestTemplate();
}
}
Or use directly:
java
RestTemplate restTemplate = new RestTemplate();
๐ค Common HTTP Methods with Examples
1. GET Request
java
String url = "https://jsonplaceholder.typicode.com/posts/1";
Post post = restTemplate.getForObject(url, Post.class);
2. POST Request
java
Post newPost = new Post("Title", "Body", 1);
Post createdPost = restTemplate.postForObject(
"https://jsonplaceholder.typicode.com/posts",
newPost,
Post.class
);
3. PUT Request
java
Post updatedPost = new Post("Updated Title", "Updated Body", 1);
restTemplate.put("https://jsonplaceholder.typicode.com/posts/1", updatedPost);
4. DELETE Request
java
restTemplate.delete("https://jsonplaceholder.typicode.com/posts/1");
5. Exchange with Headers
java
HttpHeaders headers = new HttpHeaders();
headers.set("Authorization", "Bearer your_token_here");
HttpEntity<String> entity = new HttpEntity<>(headers);
ResponseEntity<String> response = restTemplate.exchange(
"https://api.example.com/data",
HttpMethod.GET,
entity,
String.class
);
๐ฆ Example POJO
java
public class Post {
private Integer id;
private String title;
private String body;
private Integer userId;
// Getters and setters
// Constructor
}
⚠️ Deprecation Note
RestTemplate is still safe to use for simple apps.
For asynchronous or reactive apps, prefer using:
WebClient (Spring WebFlux)
25) Custom Spring Boot Application, don't use @SpringBootApplication
to create a custom Spring Boot application without using @SpringBootApplication
, giving you full control and visibility into Spring Boot's internal configuration.The annotation @SpringBootApplication
is a meta-annotation, which combines:
@Configuration
@EnableAutoConfiguration
@ComponentScan
If you want fine-grained control, you can replace it with these individually and control scanning, auto-configuration, and bean definitions explicitly.
package com.example.custom;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
@Configuration // For Java config
@EnableAutoConfiguration // Enables Spring Boot auto-config
@ComponentScan(basePackages = "com.example.custom") // Scan your packages manually
public class CustomApplication {
public static void main(String[] args) {
SpringApplication.run(CustomApplication.class, args);
}
}
26)Spring Boot REST Controller for full CRUD operations (getAllEmployees
, saveEmployee
, updateEmployee
, deleteEmployee
) using MS SQL Server and Spring Data JPA
✅ 1. Employee.java
– Entity Classpackage com.example.demo.entity;
import jakarta.persistence.*;
import lombok.*;
@Entity
@Table(name = "employees")
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Employee {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String empName;
private String gender;
private double salary;
}
✅ 2. EmployeeRepository.java
package com.example.demo.repository;
import com.example.demo.entity.Employee;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
@Repository
public interface EmployeeRepository extends JpaRepository<Employee, Long> {
}
✅ 3. EmployeeService.java
package com.example.demo.service;
import com.example.demo.entity.Employee;
import com.example.demo.repository.EmployeeRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
import java.util.Optional;
@Service
public class EmployeeService {
@Autowired
private EmployeeRepository repository;
public List<Employee> getAllEmployees() {
return repository.findAll();
}
public Employee saveEmployee(Employee employee) {
return repository.save(employee);
}
public Employee updateEmployee(Long id, Employee updatedEmployee) {
Optional<Employee> optionalEmp = repository.findById(id);
if (optionalEmp.isPresent()) {
Employee emp = optionalEmp.get();
emp.setEmpName(updatedEmployee.getEmpName());
emp.setGender(updatedEmployee.getGender());
emp.setSalary(updatedEmployee.getSalary());
return repository.save(emp);
} else {
throw new RuntimeException("Employee not found with id: " + id);
}
}
public void deleteEmployee(Long id) {
repository.deleteById(id);
}
}
✅ 4. EmployeeController.java
package com.example.demo.controller;
import com.example.demo.entity.Employee;
import com.example.demo.service.EmployeeService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import java.util.List;
@RestController
@RequestMapping("/api/employees")
public class EmployeeController {
@Autowired
private EmployeeService service;
// GET all employees
@GetMapping
public ResponseEntity<List<Employee>> getAllEmployees() {
return ResponseEntity.ok(service.getAllEmployees());
}
// POST save a new employee
@PostMapping
public ResponseEntity<Employee> saveEmployee(@RequestBody Employee employee) {
return ResponseEntity.ok(service.saveEmployee(employee));
}
// PUT update an existing employee
@PutMapping("/{id}")
public ResponseEntity<Employee> updateEmployee(@PathVariable Long id, @RequestBody Employee employee) {
return ResponseEntity.ok(service.updateEmployee(id, employee));
}
// DELETE an employee
@DeleteMapping("/{id}")
public ResponseEntity<Void> deleteEmployee(@PathVariable Long id) {
service.deleteEmployee(id);
return ResponseEntity.noContent().build();
}
}
✅ 5. Test EmployeeService
with Mockito
๐ EmployeeServiceTest.java
package com.example.demo.service;
import com.example.demo.entity.Employee;
import com.example.demo.repository.EmployeeRepository;
import org.junit.jupiter.api.*;
import org.mockito.*;
import java.util.*;
import static org.junit.jupiter.api.Assertions.*;
import static org.mockito.Mockito.*;
class EmployeeServiceTest {
@Mock
private EmployeeRepository repository;
@InjectMocks
private EmployeeService service;
private Employee sampleEmployee;
@BeforeEach
void setUp() {
MockitoAnnotations.openMocks(this);
sampleEmployee = new Employee("1", "John", "Male", 50000);
}
@Test
void testGetAllEmployees() {
when(repository.findAll()).thenReturn(List.of(sampleEmployee));
List<Employee> employees = service.getAllEmployees();
assertEquals(1, employees.size());
assertEquals("John", employees.get(0).getEmpName());
}
@Test
void testSaveEmployee() {
when(repository.save(sampleEmployee)).thenReturn(sampleEmployee);
Employee saved = service.saveEmployee(sampleEmployee);
assertNotNull(saved);
assertEquals("John", saved.getEmpName());
}
@Test
void testUpdateEmployee() {
when(repository.findById("1")).thenReturn(Optional.of(sampleEmployee));
when(repository.save(any(Employee.class))).thenReturn(sampleEmployee);
Employee updated = new Employee("1", "John Updated", "Male", 60000);
Employee result = service.updateEmployee("1", updated);
assertEquals("John Updated", result.getEmpName());
}
@Test
void testDeleteEmployee() {
service.deleteEmployee("1");
verify(repository, times(1)).deleteById("1");
}
}
27)Spring Boot REST Controller for full CRUD operations (getAllEmployees
, saveEmployee
, updateEmployee
, deleteEmployee
) using Mongo DB
✅ 1. Employee.java
– MongoDB Document
package com.example.demo.entity;
import lombok.*;
import org.springframework.data.annotation.Id;
import org.springframework.data.mongodb.core.mapping.Document;
@Data
@NoArgsConstructor
@AllArgsConstructor
@Document(collection = "employees")
public class Employee {
@Id
private String id;
private String empName;
private String gender;
private double salary;
}
✅ 2. EmployeeRepository.java
package com.example.demo.repository;
import com.example.demo.entity.Employee;
import org.springframework.data.mongodb.repository.MongoRepository;
import org.springframework.stereotype.Repository;
@Repository
public interface EmployeeRepository extends MongoRepository<Employee, String> {
}
3)EmployeeService.java & 4)
EmployeeController.java & 5)EmployeeServiceTest.java same as above
28)@scope("prototype") where to use in spring
In Spring, @Scope("prototype")
is used to define a bean scope indicating that a new instance of the bean should be created every time it is requested from the Spring container.
๐น Syntax
@Component
@Scope("prototype")
public class MyPrototypeBean {
public MyPrototypeBean() {
System.out.println("Prototype Bean Created");
}
}
You can also use:
java@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
๐ When and Where to Use @Scope("prototype")
Use Case Description Stateful beans When each client/request needs a separate instance of the bean to maintain its own state. Non-thread-safe beans To avoid sharing a single instance across threads, especially for classes that are not thread-safe. Dynamic or temporary objects For use cases like request-specific data, file uploads, or temporary tasks that should not persist beyond their use.
✅ Example in Springjava@Component
@Scope("prototype")
public class ReportGenerator {
private final UUID id = UUID.randomUUID();
public UUID getId() {
return id;
}
}
java@Component
public class ReportService {
@Autowired
private ApplicationContext context;
public void generateReports() {
ReportGenerator r1 = context.getBean(ReportGenerator.class);
ReportGenerator r2 = context.getBean(ReportGenerator.class);
System.out.println(r1.getId()); // Different UUID
System.out.println(r2.getId()); // Different UUID
}
}
๐ซ Important Notes
Prototype beans are not managed fully by Spring after creation — no lifecycle callbacks like @PreDestroy
.
Do not use @Autowired
directly on prototype-scoped beans if you're expecting new instances each time. Instead, use:
ApplicationContext.getBean(...)
ObjectFactory<T>
Provider<T>
(from javax.inject
)
๐ Singleton vs Prototype
Feature Singleton Prototype Scope One instance per container New instance per request Lifecycle Managed fully by Spring Only initialization managed Suitable for Shared, stateless beans Stateful, short-lived beans
๐งช Test Case
java@SpringBootTestpublic class PrototypeScopeTest {
@Autowired
private ApplicationContext context;
@Test
void testPrototypeScope() {
MyPrototypeBean b1 = context.getBean(MyPrototypeBean.class);
MyPrototypeBean b2 = context.getBean(MyPrototypeBean.class);
assertNotSame(b1, b2);
}
}
29) How to read properties/yml files in your java code
In Spring Boot, you can read values from .properties
or .yml
files directly into your Java code using annotations like @Value
, @ConfigurationProperties
, or via Environment
. Below are the main approaches, with examples for each.
✅ 1. Using @Value
Annotation (Simple Values)
๐น application.properties
app.name=MyApp
app.version=1.0
๐น Java Code
@Component
public class AppInfo {
@Value("${app.name}")
private String name;
@Value("${app.version}")
private String version;
public void printInfo() {
System.out.println("App Name: " + name);
System.out.println("App Version: " + version);
}
}
✅ 2. Using @ConfigurationProperties
(For Grouped Values)
๐น application.yml
app:
name: MyApp
version: 1.0
author:
name: John
email: john@example.com
๐น Java Code
@Component
@ConfigurationProperties(prefix = "app")
public class AppProperties {
private String name;
private String version;
private Author author;
// getters & setters
public static class Author {
private String name;
private String email;
// getters & setters
}
}
๐งช Usage
@RestController
public class TestController {
@Autowired
private AppProperties appProperties;
@GetMapping("/info")
public String getInfo() {
return appProperties.getName() + " by " + appProperties.getAuthor().getName();
}
}
๐ธ Don’t forget to add @EnableConfigurationProperties
if not using @SpringBootApplication
.
✅ 3. Using Environment
Object (Dynamic Access)
@Component
public class EnvReader {
@Autowired
private Environment env;
public void printProps() {
String name = env.getProperty("app.name");
String version = env.getProperty("app.version");
System.out.println("Name: " + name + ", Version: " + version);
}
}
✅ 4. Custom Properties File
If you have a separate properties file (e.g., config/myapp.properties
):
๐น File: src/main/resources/config/myapp.properties
custom.name=ExternalApp
๐น Java Code
@Configuration
@PropertySource("classpath:config/myapp.properties")
public class ExternalConfig {
@Value("${custom.name}")
private String name;
public String getName() {
return name;
}
}
๐ง Best Practices
Use Case Recommended Approach Single value @Value
Grouped structured data @ConfigurationProperties
Dynamically accessed keys Environment
External/custom config files @PropertySource
30)
@Transactional
in Spring Boot
@Transactional
in Spring Boot
The @Transactional
annotation in Spring is used to manage transaction boundaries declaratively. It ensures that a series of operations within a method are executed in a single database transaction, and if any exception occurs, all changes are rolled back automatically.
๐น What is @Transactional
?
@Transactional
marks a method (or class) to be executed within a database transaction.
๐น Where to Use?
You can use @Transactional on:
Service classes or methods (@Service)
Repository classes, although it's more common in services
๐น Why Use @Transactional?
Ensures data consistency in case of failures
Avoids partial updates
Automatically handles commit/rollback
Reduces boilerplate code for transaction management
๐น Syntax
java@Transactional
public void transferAmount() {
// DB operations
}
You can also use it on a class:
java@Transactional
@Service
public class PaymentService {
public void processPayment() {
// all methods in this class will be transactional
}
}
๐น Common Attributes
Attribute Description readOnly
If true, hints that the method should not modify data rollbackFor
Specify exceptions that should trigger rollback noRollbackFor
Specify exceptions that should not trigger rollback timeout
Maximum time (in seconds) the transaction can run propagation
Defines how nested transactions behave (see below) isolation
Defines how data integrity is handled in concurrent transactions
๐น Example
java@Transactional(rollbackFor = Exception.class)
public void createOrder(Order order) {
orderRepository.save(order);
inventoryService.reserve(order);
}
๐น Propagation Types (Most Common)
Type Description REQUIRED
(default)Join existing or create a new transaction REQUIRES_NEW
Always start a new transaction NESTED
Start a nested transaction MANDATORY
Must run in existing transaction NEVER
Must not run in a transaction SUPPORTS
Use transaction if exists NOT_SUPPORTED
Suspend any existing transaction
๐น Rollback Behavior
By default, Spring only rolls back on unchecked (Runtime) exceptions.
To rollback on checked exceptions:
java@Transactional(rollbackFor = IOException.class)
๐น Example Scenario
java@Service
public class UserService {
@Autowired
private UserRepository userRepository;
@Transactional
public void registerUser(User user) {
userRepository.save(user); // insert user
sendWelcomeEmail(user); // error occurs here
// if exception thrown, user insert is rolled back
}
public void sendWelcomeEmail(User user) {
throw new RuntimeException("Email service failed");
}
}
๐น Best Practices
✅ Always use @Transactional
at the service layer
✅ Be specific with rollbackFor
and propagation
when needed
✅ Avoid using it on private methods – it won’t work
✅ Don't call a @Transactional
method from within the same class (it won't trigger Spring proxy)