Scoped Proxy in Spring Framework
Spring framework provides scopes for spring beans.
We can control the various dependencies and configuration values that are plugged into spring bean using spring scope.
Spring supports the following six scopes. Four of six are available in a web-based application:
Scope | Description |
Singleton | It is the default scope in Spring framework. For each Spring IOC Container, only a single instance of the bean will be created. |
Prototype | Whenever a bean is requested from context, each time a new instance will be created. |
request | Scope to bean definition to HttpServlet Request. For each new request, a new bean instance will be created, It is only applicable for web-based applications. |
Session | Scope the bean definition to Http session, for each new session, a new instance of the bean will be returned, Only valid in a web-aware Spring application context. |
Application | Scope the bean definition to ServletContext. Valid only in a web-aware Spring application context. |
Web socket | Scope the bean definition to the lifecycle of the WebSocket session. Only valid in a web-aware Spring application context. |
Spring Framework provides the interfaces for creating new scopes.
1. Scopes Beans as Dependencies
Let’s assume beanA has the singleton scope and beanB has prototype scope. Suppose beanA has the beanB dependency. Then without using any additional configuration, it provides the random behavior as beanA will have a single instance for the container, but beanB will not have the same. Whenever the beanB is requested from the container a new instance will be created.
To solve these types of problem, Java spring framework provides the concept called proxy beans.
For dependencies with less scope than a parent, the framework will create the proxies rather than creating actual objects. These proxies will be extending the original objects.
Whenever the methods from beanB are called, internally it will be called on a proxy object, not on the real object. The proxy will try to get the object from context-based on the scope and it will call the original method on it.
For Example, SingletonScopedBean, PrototypeScopedBean are two beans with default and prototype scopes respectively.
public class SingletonScopedBean{ private PrototypeScopedBean prototypeScopedBean; public String getState(){ return this.prototypeScopedBean.getState(); } } Public class PrototypeScopedBean{ private final String state; public String getState() { return state; } public void setState() { this.state = UUID.randomUUID().toString(); } }
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop" xsi:schemaLocation="http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/aop https://www.springframework.org/schema/aop/spring-aop.xsd"> <bean id=”prototypeScopedBean” class=”org.example. PrototypeScopedBean” scope=”prototype” > <aop:scoped-proxy/> </bean> <bean id=”singletonScopedBean” class=”org.example. SingletonScopedBean”> <property name=”prototypeScopedBean” ref=”prototypeScopedBean”> </bean> </beans>
This will create the proxied bean for prototypeScopedBean and it will attach the proxy to singletonScopedBean as a dependency.
Whenever the getState() method is invoked on prototypeScopedBean bean, it will call the method on proxy and proxy will resolve the prototypeScopedBean instance, and it will call the getState() method on resolved object.
2. The proxies can be created in two ways
- JDK based proxies
- CGLIB (dynamic proxy) based proxies.
For creating JDK based proxies, the class must be implemented on one of the interfaces.
For CGLIB based proxies, this restriction is not there.
We can specify the proxy type using proxy-target-class attribute. If the values are true, it will create the CGLIB proxy. If the value is false, it will try to create JDK based proxy.
Annotation Approach: Spring framework provides the @Scope annotation for specifying the scope. proxyMode is the annotation attribute to specify the proxy type.
@Component @Scope(value="prototype", proxyMode=ScopedProxyMode.TARGET_CLASS) public class PrototypeScopedBean{ private final String state; public String getState() { return state; } public void setState() { this.state = UUID.randomUUID().toString(); } } @Component public class SingletonScopedBean{ @Autowired private PrototypeScopedBean prototypeScopedBean; public String getState(){ return this.prototypeScopedBean.getState(); } }
With the above changes, SingletonScopedBean will have PrototypeScopedBean bean type as a proxy.
3. Scoped Proxy in Spring – Conclusion
We learned the Spring bean scope, and how to inject the various scoped in bean dependencies. We also learned the different types of proxy modes.