Quarkus CDI

SpringBoot DI


Created by Estefanía Castro for Serbatic

Quarkus ArC

Quarkus ArC is a build-time oriented dependency injection based on CDI 2.0. Basically it is a CDI implementation.

  • ArC is not a full CDI implementation - see the list of supported features and the list of limitations.
  • The CDI APIs and annotations are defined under the root packages: javax.inject, javax.enterprise and javax.interceptor.
  • CDI is part of the core of Quarkus and most extensions need it (you don’t have to explicitly add the CDI extension)

Context and Dependency Injection (CDI):

  • Standard dependency injection framework
  • Central technology in Jakarta EE or in MicroProfile (it turns every component into an injectable, interceptable and manageable bean)
  • It is built on the concept of "loose coupling, strong typing" (beans are loosely coupled, but in a strongly-typed way)
  • It manages the scopes among beans, the context and the life cycle management (CDI events)

There are two primary parts of CDI:

  • Contexts refer to the ability to define applications by data scope
  • Dependency Injection is the ability to inject beans into others in a typesafe way, which means annotations rather than XML

It allows us to manage the lifecycle of stateful components via domain-specific lifecycle contexts and inject components (services) into client objects in a type-safe way.

Spring Boot IoC

Inversion of Control is a principle in software engineering by which the control of objects or portions of a program is transferred to a container or framework.

It can be achieved through various mechanisms such as: Strategy design pattern, Service Locator pattern, Factory pattern, and Dependency Injection (DI).

Dependency injection

  • It is a pattern through which to implement IoC, where the control being inverted is the setting of object's dependencies.
  • In this technique an object receives other objects that it depends on. These other objects are called dependencies.
  • Instead of the client specifying which service it will use, the injector tells the client what service to use. Passing the service to the client, rather than allowing a client to build or find the service, is the fundamental requirement of the pattern.

Spring IoC Container

  • The Spring IoC Container is a common characteristic of frameworks that implement IoC. It is represented by the interface ApplicationContext.
  • The Spring container is responsible for instantiating, configuring and assembling objects known as beans, as well as managing their lifecycle.
  • The org.springframework.beans and org.springframework.context packages provide the basis for the Spring Framework’s IoC container.
Spring offers support for JSR-330 standard annotations (Dependency Injection). Those annotations are scanned in the same way as the Spring annotations. You just need to add the dependency javax.inject in your pom file.

Spring Boot CGLIB

Spring generates enhanced configuration clases by creating CGLIB proxy/subclases during the initialization process so that it makes possible the inter-bean method references.

SomeConfiguration$$EnhancerBySpringCGLIB$$4b5569b2

Full configuration class

Any method invocation will be intercepted to determine if the bean has already breen created (the existing cached instance will be returned) or if the configuration class has to create the bean. This guarantees your initialization code is called just once (singleton scope).

Lite Bean Mode

Generating proxies for configuration classes takes some time and might affect your application startup time.

Lite Beans are beans that are not going to be intercepted. We can get this mode using

@Configuration(proxyBeanMethods=false)

The javadoc gives a detailed explanation for this particular field:

Specify whether {@code @Bean} methods should get proxied in order to enforce bean lifecycle behavior, e.g. to return shared singleton bean instances even in case of direct {@code @Bean} method calls in user code. (...) If this is not needed since each of this particular configuration's {@code @Bean} methods is self-contained and designed as a plain factory method for container use, switch this flag to {@code false} in order to avoid CGLIB subclass processing.(...)

@Configuration(proxyBeanMethods=true)
public class SomeConfiguration {
	@Bean
	ServiceC sharedService(){
		return new ServiceC();
	}
	@Bean
	ServiceA serviceA(){
		return new ServiceA(sharedService());
	}
	@Bean
	ServiceB serviceB(){
		return new ServiceB(sharedService());
	}
}
						
@Configuration(proxyBeanMethods=false)
public class SomeSmarterConfiguration {
	@Bean
	ServiceC sharedService(){
		return new ServiceC();
	}
	@Bean
	ServiceA serviceA(ServiceC sharedService){
		return new ServiceA(sharedService);
	}
	@Bean
	ServiceB serviceB(ServiceC sharedService){
		return new ServiceB(sharedService);
	}
}
						

Compile time DI

  • It can be achieved by manually constructing and wiring dependencies.
  • The compiler verifies that every controller in your application has access to all of the components it will need.
  • Indeed, compile-time DI (and static typing in general) can reduce the need for a subset of common types of unit tests.

Runtime DI

  • Bolier plate code is reduced, as initializing of dependencies are done by the injector component.
  • Helps to enable loose coupling and helps in Unit testing.
  • Dependency injection framework are implemented with reflection.

Thanks for join us


CDI oficial documentation
Quarkus article about CDI
Quarkus CDI examples

Springboot official doc about IoC
Springboot IoC example

Springboot DI vs Quarkus CDI