If you were asked in an interview: “What types of bean injection are there in Spring”. What would your answer be?
There are two types of bean injection in Spring: Setter-based dependency injection (DI) and Constructor-based dependency injection…
Best Practice
If you were asked: “When should you use constructor based DI and when should you use setter based DI?” A good answer would be:
Since you can mix constructor-based and setter-based DI, it is a good rule of thumb to use constructors for mandatory dependencies and setter methods or configuration methods for optional dependencies.
Proxy & Non-proxy Dependency Injection
At this point the interviewer is thinking, hey this developer is good, now lets really test him: “Tell me what other types of Bean Injection there are, I will give you a hint: the Transactional annotation”.
If you’re not sure on this answer, read on to see how Spring handles these types of annotations.
Example
If classes or methods are annotated with certain annotations like @Transactional, a proxy is injected by Spring to add extra functionality. Take a look at the following code:
@Controller public class MainController { @Autowired private FooService fooService; @GetMapping("/") public String main(Model model) { fooService.findAll(); //... } } @Service @Transactional public class FooService { @Autowired private IFooDao dao; public List findAll() { return dao.findAll(); } } @Repository public class FooDao extends AbstractJpaDAO implements IFooDao { //... }
Analysing the code, the following call sequence takes place:
MainController::main() → FooService::findAll() → AbstractJpaDAO::findAll()
However is this what happens at runtime?
Class Diagram
The class diagram above shows what happens at runtime. The following call sequence is actual what takes place:
MainController::main() → FooService$$EnhancerBySpringCGLIB$$3c710fca::findAll() → TransactionInterceptor::invoke() → FooService::findAll() → AbstractJpaDAO::findAll()
Notice how this is different to the call sequence shown above. When Spring sees the @Transactional annotation on FooService (see line 15 in code sample):
- It creates a proxy for FooService called FooService$$EnhancerBySpringCGLIB$$3c710fca
- The proxy is created as a subclass of FooService. Note the ⇾ relationship
- This proxy is responsible for using the TransactionInterceptor to inject transaction functionality, around the FooService::findAll call
- Spring then injects this proxy into MainController. In the Class Diagram notice how the call goes from FooService directly to AbstractJpaDAO (FooDao’s super class). Spring hasn’t injected a proxy here because the @Repository annotation doesn’t require a proxy.
Sequence Diagram
Read through the sequence diagram above, to see how Spring has injected @Transactional behaviour.
What other Annotations cause Spring to inject a proxy? Let us know in the comments.
Leave a Reply