ProxyMode in Spring Framework
Shant Khayalian
Co-Founder & Managing Director @ Balian's Technologies | Developing Smart Solutions from Hardware to Software | AI-Driven Management Systems & Cutting-Edge Technologies
The Spring Framework is a comprehensive and powerful framework for building enterprise-grade Java applications. One of its core features is the dependency injection (DI) mechanism, which is greatly facilitated by annotations like @Scope. Within the context of Spring, the @Scope annotation is essential for defining the scope of a bean, which determines its lifecycle and visibility within the container. One of the advanced features of the @Scope annotation is the proxyMode attribute. In this article, we'll delve deep into the concept of proxyMode, explore its types, and illustrate its usage with real-life examples to solidify our understanding.
What is @Scope in Spring?
The @Scope annotation is used to define the scope of a Spring bean. The scope essentially dictates how long a bean will be alive, how many instances will be created, and who will have access to those instances. The common scopes in Spring include:
What is a Proxy?
A proxy, in general, is an intermediary that acts on behalf of another entity. In software, a proxy object can control access to another object, serving as a placeholder or representative. Proxies come from the design pattern known as the Proxy Pattern, which is part of the Gang of Four (GoF) design patterns.
Where Did Proxies Come From?
The concept of proxies has its roots in the Proxy Design Pattern described by the GoF in their book "Design Patterns: Elements of Reusable Object-Oriented Software". This pattern is used to provide a surrogate or placeholder for another object to control access to it. Proxies are widely used in various software frameworks and architectures to introduce additional layers of abstraction and control.
Why Use Proxies?
Proxies are used for several reasons:
When to Use Proxies?
Proxies are particularly useful in scenarios where:
How Proxies Work in Spring
In Spring, proxies are used extensively to manage bean lifecycles, especially when dealing with scoped beans. When a bean's lifecycle is shorter than the lifecycle of the object that depends on it, Spring uses proxies to ensure the correct behavior. The proxyMode attribute within the @Scope annotation allows the creation of such proxies.
Types of Proxies in Spring
Spring uses two primary types of proxies: JDK dynamic proxies and CGLIB proxies.
Introducing proxyMode
The proxyMode attribute within the @Scope annotation provides an additional layer of control by allowing the creation of a proxy around the scoped bean. This is particularly useful in situations where the bean's lifecycle is shorter than the lifecycle of the object that depends on it, like in web applications.
The proxyMode can be set to one of the following values:
Real-Life Example: A Man and His Wallet
To understand proxyMode, let's consider a real-life analogy. Imagine a man named John who has a wallet. In this scenario:
John uses his wallet to hold his money, but he might need a new wallet frequently due to wear and tear. Now, let's map this analogy to a Spring application.
Without proxyMode
Without proxyMode, if John were to get his wallet injected as a prototype bean, each request for the wallet would get a new instance. This is how it would look in code:
@Component
@Scope("prototype")
public class Wallet {
// Wallet properties and methods
}
@Component
public class Man {
@Autowired
private Wallet wallet;
public Wallet getWallet() {
return wallet;
}
}
In this case, every time John accesses his wallet, he gets a new instance. However, this setup has a significant limitation. If the Man class is a singleton bean, the wallet's prototype nature is lost after the initial injection, because Spring injects a single instance of the prototype bean into the singleton.
With proxyMode
To solve this problem, we use proxyMode. By setting proxyMode to TARGET_CLASS, Spring will create a proxy that dynamically fetches the wallet instance every time it is accessed, preserving the prototype behavior:
@Component
@Scope(value = "prototype", proxyMode = ScopedProxyMode.TARGET_CLASS)
public class Wallet {
// Wallet properties and methods
}
@Component
public class Man {
@Autowired
private Wallet wallet;
public Wallet getWallet() {
return wallet;
}
}
With proxyMode set to TARGET_CLASS, every call to getWallet() will return a new instance of Wallet, ensuring that John always gets a fresh wallet, mimicking the real-life scenario where he might need a new wallet frequently.
Example 2: Car Rental Service
Consider a car rental service. The service itself (the rental agency) is a singleton, but the cars (rental vehicles) are prototypes. Every time a customer rents a car, they should get a different car.
Without proxyMode, the rental service might end up giving out the same car instance every time a customer requests a car, defeating the purpose of having multiple cars.
@Component
@Scope("prototype")
public class Car {
private String licensePlate;
public Car(String licensePlate) {
this.licensePlate = licensePlate;
}
// getters and setters
}
@Component
public class CarRentalService {
@Autowired
private Car car;
public Car rentCar() {
return car;
}
}
Using proxyMode ensures that each time a customer requests a car, they receive a different car.
@Component
@Scope(value = "prototype", proxyMode = ScopedProxyMode.TARGET_CLASS)
public class Car {
private String licensePlate;
public Car(String licensePlate) {
this.licensePlate = licensePlate;
}
// getters and setters
}
@Component
public class CarRentalService {
@Autowired
private Car car;
public Car rentCar() {
return car;
}
}
Every call to rentCar() will now return a different car instance, maintaining the correct behavior for a car rental service.
领英推荐
Practical Use Cases of proxyMode
Detailed Example: Shopping Cart in E-Commerce Application
Let's consider a more detailed example of an e-commerce application where a ShoppingCart bean is scoped to the session.
@Component
@Scope(value = "session", proxyMode = ScopedProxyMode.TARGET_CLASS)
public class ShoppingCart {
private List<Item> items = new ArrayList<>();
public void addItem(Item item) {
items.add(item);
}
public List<Item> getItems() {
return items;
}
}
@Service
public class ShoppingService {
@Autowired
private ShoppingCart shoppingCart;
public void addItemToCart(Item item) {
shoppingCart.addItem(item);
}
public List<Item> viewCart() {
return shoppingCart.getItems();
}
}
In this scenario, the ShoppingCart bean is session-scoped, meaning a new instance is created for each HTTP session. The ShoppingService is a singleton service that manages the shopping cart. By using proxyMode = TARGET_CLASS, each HTTP session will get a unique instance of ShoppingCart, allowing multiple users to shop simultaneously without interfering with each other's carts.
Understanding the proxyMode attribute in the @Scope annotation is crucial for effectively managing bean lifecycles in complex Spring applications. By leveraging proxies, developers can ensure that beans with shorter lifecycles can be properly injected into beans with longer lifecycles, maintaining the integrity and expected behavior of the application. Through real-life analogies and practical examples, we can appreciate the power and flexibility that proxyMode brings to the table, enabling robust and scalable application design.
By mastering the use of proxyMode, developers can write more modular, maintainable, and efficient code, ultimately leading to better-performing and more reliable Spring applications.
Test your Knowledge:
1. What is the purpose of the @Scope annotation in Spring?
A) To define the lifecycle and visibility of a bean within the container.
B) To define the database connection settings.
C)To configure logging levels.
2. What is a proxy in software design?
A) A direct instance of an object.
B) An intermediary that controls access to another object.
C) A database management tool.
3. Why would you use the proxyMode attribute in Spring?
A) To define the database schema.
B) To create a proxy that manages bean instances dynamically.
C) To configure the application server.
4. Which proxyMode value creates a class-based proxy using CGLIB?
A) INTERFACES
B) TARGET_CLASS
C) NO
5. In what scenario would you use a session-scoped bean with proxyMode?
A) When you want a single instance across all sessions.
B) When you need a unique instance for each user session.
C) When you want to disable session management.
6. In what scenario would you use a session-scoped bean with proxyMode?
A) A library and a book.
B) A restaurant and a dish.
C) A man and his wallet.
Find us
linkedin Shant Khayalian
Facebook Balian’s
X-platform Balian’s
web Balian’s
#SpringFramework #JavaDevelopment #DependencyInjection #ProxyPattern #WebDevelopment #EnterpriseJava #SoftwareEngineering #Programming #TechInsights #SoftwareArchitecture #Coding #JavaBeans #SpringBoot #TechEducation #LearnJava #JavaTutorial #SpringAnnotations #WebApplications #Microservices #TechProxies