Demystifying Spring. Section 2: Proxies
The proxy pattern is one of the main design patterns Spring uses to process its annotations. So let’s discuss proxies and how spring handles proxies internally.
What is a proxy?
“Proxy is a structural design pattern that lets you provide a substitute or placeholder for another object. A proxy controls access to the original object, allowing you to perform something either before or after the request gets through to the original object.”
If you are not familiar with the Proxy design pattern, go ahead and read about the Proxy pattern here.
Above code is an example for the proxy pattern. MyClassProxy
is the proxy class and it holds an instance of the implementation of MyClass
interface. When we need to call method()
, we call it through MyClassProxy.method()
, so that it executes doSomethingBefore()
and doSomethingAfter()
methods before and after calling MyClassImpl.method()
.
We can find several proxy implementations in Java. Spring uses two main proxy implementations. Those are JDK Dynamic proxy and CGLib proxy.
Dynamic Proxy
Here are some key features of the Dynamic proxy:
- No need any additional libraries: Dynamic proxy is a part of JDK, so you don’t need to add third party libraries into your project.
- Interface based: Dynamic proxy works on interfaces. That means if we want a to create a proxied bean of type MyClassImpl class, then it must implement MyClass interface.
- Proxy class generation: When you create a dynamic proxy, java runtime generates a new class on the fly known as the proxy class, that implements the same interface as the target class. This proxy class is named something similar to “$ProxyN”, where “N” is a number.
We will dive deeper into Dynamic proxies in a later article.
CGLib Proxy
- External Library: CGLib is not a part of JDK, so you need to include the CGLib library in your project’s dependencies.
- Class extension based: While Dynamic proxy works on interfaces, CGLib is based on class extensions. This means that CGLib can create proxies for classes, not just interfaces. This introduce another limitation, which is CGLib cannot proxy final classes or final methods. Because those cannot be overridden.
- Performance: CGLib proxies are much faster than Dynamic proxies, because they work by generating a subclass of the target class and override methods. But Dynamic proxy relies on reflection.
- Class names: CGLib generated proxy classes are named like
MyClass$$EnhancerBySpringCGLIB.
This class inherits from the target class and adds the necessary proxy behaviour.
Spring uses Dynamic proxy, but Springboot 2.x uses CGLib proxy. Why?
Reason is to give developers the flexibility to inject implementations.
@Autowired
StudentServiceImpl studentService;
// vs
@Autowired
StudentService studentService;
Both works in Springboot, because of the usage of CGlib.
Let’s dive deeper into Dynamic proxies and CGLib proxies on next articles.