Spring provides rich features and functions, including dependency injection, aspect-oriented programming, transaction management, data access, web application development, etc. Among them, @Configuration is an annotation in Spring. It is used to mark a class as a configuration class. Through the configuration class, Spring beans can be defined and assembled, and supports highly flexible configuration methods. In this article, we will dive into the underlying principles of @Configuration annotation, including its integration with Spring IoC containers, its definition and assembly implementation of beans, and its role and usage in the Spring framework.
@Configuration Annotation Overview
The @Configuration annotation is a new feature introduced in Spring 3.0. It is used to mark a class as a configuration class through which Spring beans can be defined and assembled.
The configuration class is a normal Java class, but the @Configuration annotation is added at the class level, indicating that this class is used to configure the creation and management of Spring Beans. A configuration class can contain multiple methods for defining a bean, marked with the @Bean annotation and returns an object that is managed by the Spring IoC container.
Configuration classes can create and assemble beans in a variety of ways, including using beans of other configuration classes, injecting other beans through dependency injection, and implementing conditional creation of beans through conditional annotations. The configuration class can be defined in XML configuration files, JavaConfig classes, annotations, etc., making Spring configuration more flexible and convenient.
The main functions of @Configuration annotations are as follows:
Definition Bean: By using the @Bean annotation in the configuration class, beans can be defined and assembled and incorporated into the management of Spring IoC containers, so that these beans can be used in applications.
Manage dependencies: The configuration class can introduce other beans through dependency injection, thereby realizing dependency management between beans. In this way, when a bean is created, other beans it depends on are automatically injected, so that dependencies between beans are conveniently managed.
Provide conditional configuration: The configuration class can implement the conditional creation of beans through conditional annotations, thereby creating different beans according to different conditions. This can be used to dynamically select the creation method of beans based on environment, configuration, etc., making the configuration more flexible.
The underlying principle
The underlying principle of @Configuration annotation mainly includes the following aspects:Spring IoC container integration, bean definition and assembly implementation, conditional configuration implementation, and configuration class loading and instantiation process。
Integration with Spring IoC containers
The integration of the @Configuration annotation with Spring IoC containers is implemented through the ConfigurationClassPostProcessor class. ConfigurationClassPostProcessor is a bean postprocessor that handles configuration classes marked with @Configuration annotations and converts them into bean definitions and registers them into Spring IoC containers.
The processing process of ConfigurationClassPostProcessor is divided intoThree stages:
Analytical stage: ConfigurationClassPostProcessor will scan the @Configuration annotation at the class level of the configuration class, parse the bean definitions and dependencies in it, and generate the corresponding BeanDefinition object.
Registration phase: ConfigurationClassPostProcessor Register the parsed BeanDefinition object into the Spring IoC container and becomes a real Spring Bean.
Verification phase: ConfigurationClassPostProcessor will verify that the bean definition and dependencies in the configuration class are correct, and an exception will be thrown if there is an error.
Through the processing of ConfigurationClassPostProcessor, the configuration classes marked by the @Configuration annotation will be parsed into real BeanDefinition objects and registered in Spring IoC containers, so that the beans defined in these configuration classes can be managed and used by Spring containers.
Definition and assembly implementation of bean
In the configuration class of @Configuration annotation tag, you can use the @Bean annotation to define a bean and incorporate it into the management of Spring IoC containers. The underlying implementation of @Bean annotation is mainly achieved throughBeanMethodclass to implement.
BeanMethodA class is an internal class that represents a method defined in a configuration class using the @Bean annotation. Each method annotated with @Bean will be represented by the BeanMethod class and contains the corresponding Bean definition information, such as the name, type, scope, initialization method, destruction method, etc. of the bean.
existAnalytical stage, ConfigurationClassPostProcessor will scan the @Bean annotation in the configuration class, parse the Bean definition information in it, and encapsulate it into a BeanMethod object. During the registration phase, ConfigurationClassPostProcessor creates the corresponding BeanDefinition object based on the BeanMethod object and registers it in the Spring IoC container.
existAssembly stage, When you need to obtain a bean defined using the @Bean annotation, the Spring IoC container will create an instance of the bean by calling the corresponding BeanMethod object method. In this way, the beans defined in the configuration class annotated by @Bean can be automatically created and assembled into other beans, realizing the function of dependency injection.
Implementation of conditional configuration
@Configuration annotation supports conditional configuration, that is, to determine whether a configuration class is loaded or a bean is created based on different conditions. The underlying implementation of this function mainly depends on the Condition interface andConditionContext、AnnotatedTypeMetadataImplementation of two interfaces.
ConditionThe interface defines a matches method to determine whether the condition is met. When a configuration class or bean uses the @Conditional annotation and passes in a class that implements the Condition interface, the Spring IoC container will call the matches method of this Condition class during the parsing stage to determine whether the condition is met. If the condition is met, the configuration class or bean will be loaded or created, otherwise it will be ignored.
ConditionContext and AnnotatedTypeMetadataThe interfaces are used to obtain the current context information and annotation metadata in the matches method of the Condition interface. ConditionContext provides a method to obtain information such as BeanFactory, Environment, ResourceLoader, ClassLoader, etc., which can be used to judge the status of the current environment. AnnotatedTypeMetadata provides a method to obtain annotation information of the configuration class or bean, which can be used to determine whether the attribute value of the annotation meets the conditions.
Through the implementation of these interfaces, the @Conditional annotated configuration class or bean can be dynamically loaded or created according to different conditions, thus realizing the function of conditional configuration.
The loading and instantiation process of configuration classes
@Configuration The loading and instantiation process of the configuration class marked with the @Configuration annotation in the Spring IoC container mainly includes the following steps:
Loading configuration classes: When the Spring IoC container starts, all configuration classes are scanned and loaded into the container. This process is implemented through the ConfigurationClassParser class.
The ConfigurationClassParser class is responsible for parsing annotations in the configuration class, including @Configuration, @Bean, @ComponentScan and other annotations, and generating corresponding BeanDefinition objects. Among them, the @ComponentScan annotation is used to specify the packages that need to be scanned, so as to find other configuration classes and bean definitions.
Analyze bean definitions and dependencies: During the process of loading the configuration class, ConfigurationClassParser will parse the @Bean annotation in the configuration class and generate the corresponding BeanDefinition object. At the same time, it will parse other annotations in the configuration class, such as @Autowired, @Value and other annotations, thereby generating dependencies between beans.
Register Bean Definition: After parsing the bean definition and dependency, ConfigurationClassParser will register the generated BeanDefinition object into the Spring IoC container. This process is implemented by calling the registerBeanDefinition method of the BeanDefinitionRegistry interface.
Instantiated bean: When you need to obtain a bean, the Spring IoC container instantiates the bean and puts it into the container according to the bean's definition information. This process is implemented by calling the getBean method of the BeanFactory interface.
During the instantiation of a bean, the Spring IoC container will first determine whether the bean already exists in the container. If it exists, the existing bean instance is directly returned; if it does not exist, a new bean instance will be created through the bean definition information.
Creating a BeanExampleWhen the Spring IoC container first checks whether the constructor of the bean has parameters. If there are parameters, the corresponding bean instance will be obtained from the container according to the parameter type or parameter name and passed into the constructor. If there are no parameters, the parameterless constructor is called directly to create the Bean instance.
After creating a bean instance, Spring IoC containers will initialize the bean, including calling the initialization method of the bean (such as the method of the @PostConstruct annotation mark), applying the property value of the bean (such as the attribute of the @Value annotation mark), processing the life cycle callback of the bean (such as the implementation of the InitializingBean and DisposableBean interfaces), etc.
Finally, the created bean instance will be placed in the container and can be accessed and used by the name or type of the bean.
Summarize
The @Configuration annotation is one of the important annotations used in the Spring framework to mark configuration classes. It allows us to configure and manage Bean instances through Java classes, thus implementing object-oriented configuration.
The underlying principle of @Configuration annotation involves multiple aspects such as proxy objects, circular dependency solutions, refresh mechanisms, and conditional configuration. By deeply understanding the principles of @Configuration annotations, we can better understand how to configure in the Spring framework and apply it flexibly in actual projects.
When using @Configuration annotations, you need to pay attention to some common usage principles, such as avoiding the use of @Autowired annotations in configuration classes, avoiding circular dependencies, and rationally using conditional configurations. At the same time, a deep understanding of the source code implementation of @Configuration annotation is also very helpful for troubleshooting and solving configuration-related problems.
The above is a detailed explanation of Spring annotations @Configuration. For more information about Pring annotations @Configuration, please follow my other related articles!