Spring Context
Spring Context is a container that instantiates, configures, and manages a set of objects (beans) that are defined with a configuration metadata.
- Dependency Injection (DI) container;
- Given a set of type information, including their dependencies, it creates the graph of component instances;
- System that allows us to manage the composition and life cycle of objects and their dependencies, dynamically;
- The context is the Spring component responsible for instantiating and managing instances, such as controller instances.
Dependency Injection (DI) and Inversion of Control (IoC)
- Creation of the application graph of objects;
- Instantiation of the objects and their dependencies, passing the dependencies to the objects.
The dependent object receives and uses the dependencies, but it does not create them.
- Constructor injection: Dependency injection through the constructor - the preferable way of dependency injection;
- Field/Property injection: Dependencies are passed in after object creation, via the assignment of fields or the executions of property setter methods:
- Requires mutable dependency fields;
- Objects are not ready to operate after construction;
- Use only when the constructor injection is not possible;
- Wiring: Establish the dependencies between objects;
- Class stereotype: Containers of functionality (components) vs containers of data.
Examples
Steps:
- Creation of the context;
- Add the bean definitions to the context;
- Refresh the context, to take in consideration the new bean definitions;
- Use the context to get the beans.
Bean: A bean is an object that is created and managed by the context.
1st Example
Considering the following classes and dependencies (dependent -> dependency):
ComponentC -> ComponentB -> ComponentA
// Create the context
val context = AnnotationConfigApplicationContext()
// Add the bean definitions
context.register(
ComponentA::class.java,
ComponentB::class.java,
ComponentC::class.java
)
// Refresh the context
context.refresh()
// Get the beans (example: ComponentB)
val componentB = context.getBean<ComponentB>()
- If the ComponentA was not registered, the context would not be able to create the ComponentB, throwing an exception;
- If the ComponentB was not registered, the context would not be able to create it, throwing an exception.
2nd Example
You can also add the bean definitions given a package, using the scan method. In this case, the context will search for the classes annotated with @Component and register them:
// Create the context
val context = AnnotationConfigApplicationContext()
// Add the bean definitions
context.scan("package.name")
Note: You can also use the context with components initialized with lists of dependencies. This can be useful, for example, when creating a router, where you can have a list of controllers and inject them into the router.
3rd Example
If a component registered in the context is not initialized by a constructor, but with a static method, you can use the @Bean annotation to register it.
For example, a HttpClient is initialized with the newBuilder method, so we create a function that returns a HttpClient and annotate it with @Bean:
@Configuration
class BeanConfig {
@Bean
fun httpClient(cookieHandler: CookieHandler): HttpClient = HttpClient
.newBuilder()
.cookieHandler(cookieHandler)
.build()
}
// Create the context
val context = AnnotationConfigApplicationContext()
// Add the bean definitions
context.register(BeanConfig::class.java)
Container Overview
BeanFactory: The core container interface;ApplicationContext: The interface that extends theBeanFactory;AnnotationConfigApplicationContext: The class that implements theAbstractApplicationContextand is used to create the context from annotations.
The Spring context is a DI container that needs configuration metadata to create the application objects. The metadata can be provided in different ways:
- XML configuration files;
- Java annotations or code.
Annotation-based Container Configuration
- The
@Configurationannotation indicates that a class declares one or more@Beanmethods and may be processed by the Spring container to generate bean definitions and service requests for those beans at runtime; - The
@Beanannotation tells Spring that a method annotated with@Beanwill return an object that should be registered as a bean in the Spring application context; - The
@Autowiredannotation is used to autowire bean on the setter method, constructor or a property; - The
@Componentannotation is a generic stereotype for any Spring-managed component;- The
@Serviceannotation is a specialization of the@Componentannotation for service layer; - The
@Repositoryannotation is a specialization of the@Componentannotation for persistence layer; - The
@Controllerannotation is a specialization of the@Componentannotation for presentation layer (check the next section for more details).
- The