This article is shared from Huawei Cloud Community " The Road to Spring Master 9 - Mastering the Secret Weapon of Spring Conditional Assembly ", author: Zhuanyeyang__.
In the Spring framework, conditional assembly is a powerful feature that can help us better manage and control the Bean creation process. This article explains in detail how to use Spring's @Profile and @Conditional annotations to implement conditional assembly. Through specific examples, you can better understand the usage and applicable scenarios of these two annotations. In-depth study of these annotations can help improve the skills of Spring application development and better grasp the Spring framework.
1. Conditional assembly
1.1 Understanding conditional assembly and its important role in Spring
In Spring
the framework, conditional assembly ( Conditional Configuration
) is a very important feature, which allows developers to dynamically Bean
register or create according to the conditions met. In this way, different Bean
instances can be created according to different environments or configurations. This feature is very useful for creating configurable and modular applications.
Spring
A series of annotations are provided to implement conditional assembly, including:
-
@Profile : This isthe annotation. This annotation means that only when the specific oneis activated, the one with the annotation is created. We can set the activation in the application configuration file.
Spring
Profile
Bean
Profile
-
@Conditional : This is the annotation that takes one or more classes that need to implement the interface and override its methods. Annotated ones are created only when all methods of the class return.
Spring
Condition
Condition
matches
Condition
matches
true
@Conditional
Bean
The following annotations are provided, mainly for auto-configuration functions: Spring Boot
-
@ConditionalOnProperty : This annotation indicates that only when one or more given properties have a specific value, create a property with this annotation
Bean
. -
@ConditionalOnClass and @ConditionalOnMissingClass : These two annotations indicate that
Classpath
only when there is (or is not) a specific class among them, the one with this annotation will be createdBean
. -
@ConditionalOnBean and @ConditionalOnMissingBean : These two annotations indicate that only
Spring ApplicationContext
when there is (or is not) specificBean
, the one with the annotation is createdBean
.
By combining these annotations, developers can implement complex conditional assembly logic and flexibly control Spring
application configuration and behavior.
2. @Profile
In , it is used to solve the needs of different configurations in different environments, and it can assemble applications according to the requirements of specific environments. For example, we may have a set of configurations for the development environment and another set of configurations for the production environment, which can be used . It can determine which environment is active at runtime, and then decide which ones to register . Spring
Profile
Profile
bean
2.1 Actual application scenarios based on @Profile
For example, we may need to use a different database or a different service endpoint.
Here we can take the database configuration as an example. The databases in the development environment, test environment, and production environment may be different. We can configure the databases of these environments separately through annotations. @Profile
@Configuration public class DataSourceConfiguration { @Value("${spring.datasource.username}") private String username; @Value("${spring.datasource.password}") private String password; @Value("${spring.datasource.url}") private String url; @Bean @Profile("dev") public DataSource devDataSource() { return DataSourceBuilder.create() .username(username) .password(password) .url(url + "?useSSL=false&serverTimezone=Asia/Shanghai") .driverClassName("com.mysql.cj.jdbc.Driver") .build(); } @Bean @Profile("test") public DataSource testDataSource() { return DataSourceBuilder.create() .username(username) .password(password) .url(url + "?useSSL=false&serverTimezone=Asia/Shanghai") .driverClassName("com.mysql.cj.jdbc.Driver") .build(); } @Bean @Profile("prod") public DataSource prodDataSource() { return DataSourceBuilder.create() .username(username) .password(password) .url(url + "?useSSL=true&serverTimezone=Asia/Shanghai") .driverClassName("com.mysql.cj.jdbc.Driver") .build(); } }
In actual development, different environments have different Apollo
configurations Apollo
, and the database connection configuration is written on it. There is no need for multiple codes for production and testing Bean
, and you only need to load different Apollo
configurations to establish a database connection.
Apollo
It is a distributed configuration center open sourced by Ctrip's framework department, which can centrally manage the configuration information of applications.Apollo
The main goal of is to enable applications to dynamically adjust their configuration at runtime without redeployment.
Apollo
and solve the same problem - how to manage the configuration of different environments, butSpring
provide more powerful functions, especially in large-scale and complex distributed systems. In addition, it also supports configuration version control, audit logs, rights management and other functions, providing a comprehensive solution for configuration management.Profile
Apollo
Apollo
2.2 Understand the working principle and purpose of @Profile
Let's use the library opening hours example, and use the configuration to control the opening hours. Spring Profiles
The whole code is as follows:
First, we need a class representing the opening hours : LibraryOpeningHours
package com.example.demo.bean; public class LibraryOpeningHours { private final String openTime; private final String closeTime; public LibraryOpeningHours(String openTime, String closeTime) { this.openTime = openTime; this.closeTime = closeTime; } @Override public String toString() { return "LibraryOpeningHours{" + "openTime='" + openTime + '\'' + ", closeTime='" + closeTime + '\'' + '}'; } }
Then, we need a class to hold this open time: Library
package com.example.demo.bean; public class Library { private final LibraryOpeningHours openingHours; public Library(LibraryOpeningHours openingHours) { this.openingHours = openingHours; } public void displayOpeningHours() { System.out.println("Library opening hours: " + openingHours); } }
Next, we need to define two different configurations, representing the opening hours on weekdays and weekends:
package com.example.demo.configuration; import com.example.demo.bean.Library; import com.example.demo.bean.LibraryOpeningHours; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Profile; @Configuration @Profile("weekday") public class WeekdayLibraryConfiguration { @Bean public LibraryOpeningHours weekdayOpeningHours() { return new LibraryOpeningHours("8:00 AM", "6:00 PM"); } @Bean public Library library(LibraryOpeningHours openingHours) { return new Library(openingHours); } }
Opening hours on weekdays are morning 8
and evening 6
.
package com.example.demo.configuration; import com.example.demo.bean.Library; import com.example.demo.bean.LibraryOpeningHours; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Profile; @Configuration @Profile("weekend") public class WeekendLibraryConfiguration { @Bean public LibraryOpeningHours weekendOpeningHours() { return new LibraryOpeningHours("10:00 AM", "4:00 PM"); } @Bean public Library library(LibraryOpeningHours openingHours) { return new Library(openingHours); } }
Opening hours on weekends are morning 10
and afternoon 4
.
Finally we run in the main program and change the opening hours of the library by selecting different : Profile
package com.example.demo.application; import com.example.demo.bean.Library; import com.example.demo.configuration.WeekdayLibraryConfiguration; import com.example.demo.configuration.WeekendLibraryConfiguration; import org.springframework.context.annotation.AnnotationConfigApplicationContext; public class DemoApplication { public static void main(String[] args) { AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(); context.getEnvironment().setActiveProfiles("weekday"); context.register(WeekdayLibraryConfiguration.class, WeekendLibraryConfiguration.class); context.refresh(); Library library = context.getBean(Library.class); library.displayOpeningHours(); } }
Some friends here may have doubts, why do we need to have a method setActiveProfiles
in the future ?register
refresh
setActiveProfiles
method is used to specify which ones Profile
are active, and simply setting the active one Profile
does not trigger Spring
the container to instantiate the corresponding one bean
.
register
The method is to register the configuration class Spring
in the application context, it does not immediately create the declaration in the configuration class bean
, and bean
the creation process of these is refresh
carried out in the phase of the context. At this stage, Spring
the container will read all configuration classes and @Bean
parse the annotated methods in the configuration classes before creating and initializing them bean
.
So, if you refresh
try to get one of the configuration classes before calling the method bean
, you will not find it, because it bean
may not have been created yet. Only after the context is refreshed (that is, the method is called refresh
), all bean
will be created and registered in Spring
the container, and then they can be obtained through the context bean
.
operation result:
If we choose , the library will be open on weekdays; if we choose , the library will be open on weekends. "weekday" Profile
"weekend" Profile
Note: register
methods, @Component
, @Bean
, @Import
are all ways to register Bean
to Spring
the container, they have different applicable scenarios and working methods:
-
register method : This method is used to register one or more configuration classes (that is, classes marked with
@Configuration
annotations)Spring
intoApplicationContext
. This process is to add the meta information of the configuration class to the context, but it does not instantiate it immediatelyBean
. The actualBean
instantiation process will happen atApplicationContext
refresh time (that is,refresh
when the method is called), and this process may be affected by conditional assembly annotations such as@Profile
.@Conditional
-
@Component : This is a generic annotation that can be used to mark any class as
Spring
a component. If an annotated@Component
class isSpring
under the component scanning path, itSpring
will be automatically createdBean
and added to the container. -
@Bean : This annotation is usually used on methods in configuration classes. Annotated
@Bean
methods indicate how to instantiate, configure, and initialize a newBean
object.Spring IoC
The container will be responsible for calling these methods at the appropriate time (duringApplicationContext
the refresh phase) to createBean
the instance. -
@Import : This annotation is used to import other configuration classes in a configuration class. By using this annotation, we can
Bean
disperse the definition of config into multiple configuration classes for better modularity and organization.
In Spring
the framework, the above methods and annotations work together to provide powerful dependency injection and management capabilities, and support us to create complex and modular applications.
In Spring
the framework, refresh
methods are used to start Spring
the life cycle of the application context, which dominates the resolution, creation and initialization process ApplicationContext
in the framework Bean
. Here are refresh
the main steps of the method in action:
-
Read all registered configuration classes:
refresh
The method first scansApplicationContext
all registered configuration classes (usually@Configuration
classes marked with annotations). It looks for all@Bean
annotated methods in these configuration classes. -
Parsing
@Bean
method: For each@Bean
method, how to create and configure the corresponding method will be determinedSpring
based on the method's signature, return type, and possible other annotations (such as@Scope
,@Lazy
, etc.) .@Profile
Bean
-
Bean
Creation and dependency injection: Based on the information obtained by parsing,Spring IoC
the container will createBean
instances on demand. After instantiationBean
, this dependencySpring
is also processed , i.e. it will automatically inject the other that this depends on into its properties or constructor parameters.Bean
Bean
Bean
-
Initialization: If the interface
Bean
is implementedInitializingBean
or annotated methods are defined , these initialization methods will be called@PostConstruct
after all dependency injection is complete .Spring
Therefore, after calling refresh
the method, we can be sure that everything defined in the configuration class Bean
has been correctly parsed, created, and registered in Spring
the ApplicationContext
. This includes Bean
instantiation, dependency injection, and possibly initialization.
The above steps are not necessarily performed sequentially. In fact, some optimizations and adjustments may be made Spring
by IoC
the container when processing these steps. The specific processing order may be affected by the following factors:
-
Bean dependencies : If one
Bean A
depends on the otherBean B
, itSpring
needs to be created and initializedBean B
before it can be createdBean A
. This may result inBean
a different order of creation than the order in which they were defined in the configuration class. -
Bean lifecycle and scope : For example, if one
Bean
is a singleton (the default scope), then it will usually be created when the container starts. But if it's prototypical, it's only created when it's needed. -
Conditional annotations : Conditional annotations like
@Profile
and may also affect the creation of . If the condition is not met, the corresponding one will not be created.@Conditional
Bean
Bean
Although in general, it is true that the life cycle will be processed according to the steps of Spring
"reading configuration class-parsing @Bean
method-creating -dependency injection-initialization" , the specific processing process may be affected by the above-mentioned The influence of various factors.Bean
Bean
Keep in mind the library opening hours example, many examples will follow around this example.
2.3 Why is there @Profile? Doesn't the application have configuration files for various environments?
application-dev.yml
, application-test.yml
and these configuration files can be used to specify different configuration parameters in different environments, such as database connection strings, service addresses, and so on. application-prod.yml
Compared with application
configuration files, @Profile
annotations provide a higher level of environmental difference control in the application, which can control the entire or configuration class, not just configuration parameters. With this , we can make the entire or configuration class only take effect in a specific environment, which means that we can use completely different implementations or different configuration methods according to the environment. Spring
Bean
@Profile
Bean
Bean
To give an example, consider a mail service, we may use a simulated mail service in the development environment, just simply print out the content of the mail, and in the production environment we may need to use an actual mail service. We can create two , one with annotations and one with annotations. In this way, we can choose which mail service to use according to the environment without changing other codes. Bean
@Profile("dev")
@Profile("prod")
In general, application-{profile}.yml
files and annotations are provided environmental difference management tools, which are used to manage configuration parameters and /or configuration classes respectively, and can be selected according to the specific needs of the application. @Profile
Spring
Bean
2.4 How to determine the active Profile in Spring?
Spring
The current activity can be specified in a number of ways Profile
, in order of priority from high to low as follows:
- ConfigurableEnvironment.setActiveProfiles
- JVM's -Dspring.profiles.active parameter or environment variable SPRING_PROFILES_ACTIVE (available only for Spring Boot)
- SpringApplicationBuilder.profiles (available only for Spring Boot)
- SpringApplication.setDefaultProperties (available only for Spring Boot)
- Profile property spring.profiles.active
If there are configurations above, the configuration with higher priority will override the configuration with lower priority.
Let's take a look at them separately. Here we take 2.1
the example of the section as the basis, only modify the main program, and do not put other repeated codes:
1.ConfigurableEnvironment.setActiveProfiles:
This is Spring
a framework API
, so it can be Spring Boot
used not only in , but also in native applications. We can set the activity Spring
through the obtained environment .ApplicationContext
Profile
package com.example.demo.application; import com.example.demo.configuration.WeekdayLibraryConfiguration; import org.springframework.context.annotation.AnnotationConfigApplicationContext; public class DemoApplication { public static void main(String[] args) { AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(); context.getEnvironment().setActiveProfiles("weekday"); context.register(WeekdayLibraryConfiguration.class); context.refresh(); // 下面这行调试使用 String[] beanDefinitionNames = context.getBeanDefinitionNames(); } }
operation result:
Here you can see WeekdayLibraryConfiguration
that it has been created, but WeekendLibraryConfiguration
not created.
2. JVM's -Dspring.profiles.active parameter and environment variable SPRING_PROFILES_ACTIVE (available only for Spring Boot)
Both of these are features, and there is no built-in support in Spring Boot
native applications. The main program we use here demonstratesSpring
Spring Boot
- Configure -Dspring.profiles.active parameter
For example, when starting an Spring Boot
application, we can use the following command:
-Dspring.profiles.active=weekend
In this example, -Dspring.profiles.active=weekend
it is the part that sets the system properties, indicating that only those marked as @Profile("weekend")
will Bean
be created and used.
Let's use 2.1
the example in the above section to modify the code and set the system properties
Or configure like this
Spring Boot
Main program:
package com.example.demo.application; import com.example.demo.configuration.WeekendLibraryConfiguration; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.context.ConfigurableApplicationContext; import org.springframework.context.annotation.ComponentScan; @SpringBootApplication @ComponentScan("com.example") public class DemoApplication { public static void main(String[] args) { ConfigurableApplicationContext context = SpringApplication.run(DemoApplication.class, args); WeekendLibraryConfiguration bean = context.getBean(WeekendLibraryConfiguration.class); System.out.println(bean.weekendOpeningHours()); } }
Profile
There are only for- weekend
purposes here bean
, but Profile
for weekday
-purposes bean
have not been created, you can debug and verify by yourself.
The result of the operation is as follows:
- Configure the environment variable SPRING_PROFILES_ACTIVE
We can set it in the environment variables of the operating system SPRING_PROFILES_ACTIVE
.
In Unix/Linux
the system, we can use commands to set environment variables before starting the application export
. For example:
export SPRING_PROFILES_ACTIVE=dev java -jar myapp.jar
In Windows
the system, we can use set
the command to set environment variables:
set SPRING_PROFILES_ACTIVE=dev java -jar myapp.jar
3. SpringApplicationBuilder.profiles (available only for Spring Boot)
package com.example.demo.application; import com.example.demo.configuration.WeekendLibraryConfiguration; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.builder.SpringApplicationBuilder; import org.springframework.context.ConfigurableApplicationContext; import org.springframework.context.annotation.ComponentScan; @SpringBootApplication @ComponentScan("com.example") public class DemoApplication { public static void main(String[] args) { ConfigurableApplicationContext context = new SpringApplicationBuilder(DemoApplication.class) .profiles("weekend") .run(args); WeekendLibraryConfiguration bean = context.getBean(WeekendLibraryConfiguration.class); System.out.println(bean.weekendOpeningHours()); } }
operation result:
4. SpringApplication.setDefaultProperties (available only for Spring Boot)
SpringApplication.setDefaultProperties
The method is used to set default properties, which can set a series of default properties, including spring.profiles.active
properties. When spring.profiles.active
a property is set, Spring
it is considered to be currently active Profile
.
Main program:
package com.example.demo.application; import com.example.demo.configuration.WeekdayLibraryConfiguration; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.context.ConfigurableApplicationContext; import org.springframework.context.annotation.ComponentScan; import javax.annotation.Resource; import java.util.Properties; @SpringBootApplication @ComponentScan(basePackages = "com.example.demo") public class DemoApplication { @Resource private WeekdayLibraryConfiguration weekdayLibraryConfiguration; public static void main(String[] args) { SpringApplication application = new SpringApplication(DemoApplication.class); Properties props = new Properties(); props.put("spring.profiles.active", "weekday"); application.setDefaultProperties(props); ConfigurableApplicationContext context = application.run(args); // 验证当前激活Profile String[] activeProfiles = context.getEnvironment().getActiveProfiles(); for (String profile : activeProfiles) { System.out.println("当前活动Profile:" + profile); } } }
operation result:
5. Configuration file property spring.profiles.active configuration file
In application.properties
or application.yml
files, we can set spring.profiles.active
properties.
For example, in application.properties
the file we can add the following lines:
spring.profiles.active=weekday
In application.yml
the file we can add the following:
spring: profiles: active: weekday
3. @Conditional
3.1 @Conditional annotation and its use
@Conditional
is Spring 4.0
a core annotation introduced in to Bean
associate the creation of a with a specific condition. This feature Spring Boot
is heavily used in , to create and assemble when certain conditions are met Bean
.
@Conditional
The annotation accepts one or more classes that implement Condition
the interface as parameters. Condition
The interface has only one matches
method named , which needs to return a boolean value to indicate whether the condition is met or not. If matches
the method returns true
, Spring
this will @Conditional
be created and assembled Bean
; if it returns false
, this will not be created and assembled Bean
.
@Conditional
The application of annotations is very flexible. It can be used to mark classes that use annotations directly or indirectly @Component
, including but not limited to @Configuration
classes. Additionally, it can be used to mark @Bean
methods, or as a meta-annotation to compose custom annotations.
If a @Configuration
class is marked with an annotation, all methods @Conditional
associated with that class , as well as any and annotations, are also subject to the same conditions. This means that these methods and annotations will only be processed if the condition of the method is met.@Bean
@Import
@ComponentScan
@Conditional
Overall, @Conditional
provides a powerful mechanism that can be used to control Bean
the creation and assembly based on certain conditions. By using it, we can more flexibly control Spring
the configuration of the application in order to adapt to various operating environments and requirements.
3.2 Use @Conditional to implement conditional assembly
Suppose we have a library application where we have two classes, Librarian
and Library
we want the class to be created only if it exists . At this time, it cannot be realized, because it is impossible to check whether the other exists. Librarian
Library
@Profile
@Profile
bean
The whole code is as follows:
First, we create Librarian
the class:
package com.example.demo.bean; public class Librarian { }
create Library
class
package com.example.demo.bean; public class Library { // Library class private final String libraryName; public Library(String libraryName) { this.libraryName = libraryName; } public void showLibraryName() { System.out.println("Library name: " + libraryName); } }
Next, we create a conditional class to check for the existence of the definition of Librarian
:bean
package com.example.demo.condition; import org.springframework.context.annotation.Condition; import org.springframework.context.annotation.ConditionContext; import org.springframework.core.type.AnnotatedTypeMetadata; public class LibrarianCondition implements Condition { @Override public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) { return context.getBeanFactory().containsBeanDefinition("librarian"); } }
Here a conditional class named is defined LibrarianCondition
, implements Condition
the interface and overrides matches
the method. In matches
the method, a check is made to see if a definition named " " Spring
exists in the application context .librarian
Bean
Then, we need to create a configuration class that defines a condition that will only be created if Librarian bean
it exists :Library bean
package com.example.demo.configuration; import com.example.demo.bean.Librarian; import com.example.demo.bean.Library; import com.example.demo.condition.LibrarianCondition; import org.springframework.context.annotation .Bean; import org.springframework.context.annotation.Conditional; import org.springframework.context.annotation.Configuration; @Configuration public class LibraryConfiguration { /** * Change the existence of Librarian bean by commenting or uncommenting librarian method , so as to observe the impact on the creation of the Library bean. * * @return */ @Bean public Librarian librarian() { return new Librarian(); } @Bean @Conditional(LibrarianCondition.class) public Library library() { return new Library("The Great Library"); } }
In the above code, an annotation Library Bean
is added to the created method @Conditional(LibrarianCondition.class)
, specifying that it will be created only when it returns . We can then comment or uncomment methods to change the state of existence to observe its effect on creation. LibrarianCondition
true
Library bean
librarian()
Librarian bean
Library bean
Finally, in the main program, we initialize Spring
the context and Library
get bean
:
package com.example.demo; import com.example.demo.configuration.LibraryConfiguration; import org.springframework.context.annotation.AnnotationConfigApplicationContext; public class DemoApplication { public static void main(String[] args) { AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(); context.register(LibraryConfiguration.class); context.refresh(); System.out.println("IOC容器是否有librarian?" + context.containsBean("librarian")); System.out.println("IOC容器是否有library?" + context.containsBean("library")); } }
In this example, Library
the will bean
only be created if Librarian
the also bean
exists.
When Librarian
present, the output is:
When Librarian
not present, the output is:
3.2 Application of @Conditional in Spring Boot
Spring Boot
It is used in many places to achieve conditional configuration, let's take a look at it separately. @Conditional
3.2.1 @ConditionalOnBean 和 @ConditionalOnMissingBean
@ConditionalOnBean
and are a pair of conditional annotations provided for conditional creation , which can check whether a specific container exists . If such is present (or absent) , then the corresponding configuration will be enabled (or ignored). @ConditionalOnMissingBean
Spring Boot
Spring Beans
Spring
bean
bean
Specifically:
-
@ConditionalOnBean : When the specified type exists in the container , the currently annotated one will be created.
Spring
Bean
Bean
-
@ConditionalOnMissingBean : When the specified type does not exist in the container , the currently annotated one will be created.
Spring
Bean
Bean
Here we select @ConditionalOnBean
annotations for explanation. Modify our configuration class just now, we delete Condition
the condition judgment class that implements the interface LibrarianCondition
, and @Conditional
change it to@ConditionalOnBean
package com.example.demo.configuration; import com.example.demo.bean.Librarian; import com.example.demo.bean.Library; import org.springframework.boot.autoconfigure.condition.ConditionalOnBean; import org.springframework.context .annotation.Bean; import org.springframework.context.annotation.Configuration; @Configuration public class LibraryConfiguration { /** * By commenting or uncommenting the librarian method, change the existence status of the Librarian bean, so as to observe the impact on the creation of the Library bean . * * @return */ @Bean public Librarian librarian() { return new Librarian(); } @Bean @ConditionalOnBean(Librarian. class) public Library library() { return new Library("The Great Library"); } }
As shown below:
Next, change the main program Spring Boot
to restart
package com.example.demo; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.context.ConfigurableApplicationContext; @SpringBootApplication public class DemoApplication { public static void main(String[] args) { ConfigurableApplicationContext context = SpringApplication.run(DemoApplication.class); System.out.println("IOC容器是否有librarian?" + context.containsBean("librarian")); System.out.println("IOC容器是否有library?" + context.containsBean("library")); } }
The result of the operation is as follows:
When Librarian
present, the output is:
When Librarian
not present, the output is:
Some people may wonder, is it possible to register later, so that this condition will be considered Librarian
non -existent?Library
Librarian
The answer is no. Spring
When processing a class, all methods are pre-resolved, all definition information is collected , and these are instantiated according to dependencies . @Configuration
@Bean
Bean
Bean
If it Librarian
is not written in the configuration class, but modified by @Component
annotations, will the condition be judged as non-existent due to the order problem?
Even if the class definition is annotated and registered to the container through component scanning, dependencies can still be handled correctly, and it depends on the definition, not the instantiation. Librarian
@Component
Spring
Spring
Bean
Bean
When the container starts, it first scans all definitions and collects information, including those defined by class methods, as well as those registered through annotations such as , , and component scanning mechanisms. Spring
Bean
@Configuration
@Bean
@Component
@Service
@Repository
When the conditional judgment of or is executed , you already have a global vision and know all the definitions. Therefore, even if one is defined through annotations and registered by the component scanning mechanism, the judgment will not fail due to order problems. Similarly, conditional judgments will not have this problem. @ConditionalOnBean
@ConditionalOnMissingBean
Spring
Bean
Bean
@Component
@Conditional
In general, Spring
it provides powerful dependency management and automatic assembly functions, which can ensure the judgment of various conditions, no matter how they are defined and registered. Bean
Bean
3.2.2 @ConditionalOnProperty
This annotation indicates that only when one or more of the given properties have a specific value, only create with the annotation Bean
.
@ConditionalOnProperty
It is Spring Boot
an annotation in , which is used to check whether a certain configuration property exists, or whether it has a specific value. Only when the conditions are met, the class or method marked by the annotation will be created or executed. This annotation can be used to enable or disable certain functions in different environments, or to adjust the behavior of functions.
In actual business, we may decide whether to enable a certain Bean
function or not according to different configurations. Take the following code as an example:
@Configuration public class MyConfiguration { @Bean @ConditionalOnProperty(name = "my.feature.enabled", havingValue = "true", matchIfMissing = true) public MyFeature myFeature() { return new MyFeature(); } }
In this example, MyFeature
this will only be created if the value of the property Bean
in the configuration file is . If there is no such property in the configuration file , it will still be created because of the value of the property .my.feature.enabled
true
my.feature.enabled
matchIfMissing
true
MyFeature
Bean
In this way, we can flexibly enable or disable a certain function by modifying the configuration file without modifying the code. For example, we may have some features that behave differently in the development environment and the production environment, or some optional features that can be turned on or off according to needs. These functions can also be considered for use in actual development Apollo
. You only need to configure the corresponding environment Apollo
to obtain the corresponding attribute values, so as to realize different functions.
3.2.3 @ConditionalOnClass 和 @ConditionalOnMissingClass
These two annotations can be checked Classpath
for the presence or absence of a particular class.
For example, we may have a service that requires Classpath
a certain class to work properly, we can configure it like this:
@Service @ConditionalOnClass(name = "com.example.SomeClass") public class MyService { // ... }
In this example, if com.example.SomeClass
exists Classpath
in , MyService
it will be created and added Spring
to ApplicationContext
. If the class does not exist, it MyService
will not be created.
Similarly, we can also use annotations to create a certain class when it does not exist , just replace the above code with . @ConditionalOnMissingClass
Classpath
Bean
@ConditionalOnClass
@ConditionalOnMissingClass
This 2
annotation is rarely used in actual business development, because it is mainly used to deal with some general logic of the underlying framework or library. But it is really useful in the development of frameworks or libraries, so that the framework or library can be more flexibly adapted to different usage environments and configurations.
For example, in , many auto-configuration classes use conditional assembly. For example, this class is responsible for automatically configuring the database connection pool. It uses annotations to determine whether there is a related database driver class in the database. Only when there is a related database driver class, it will be automatically configured. Spring Boot
DataSourceAutoConfiguration
@ConditionalOnClass
Classpath
For another example, we may have developed a powerful logging library that can log to the database, but if the user's project does not include a driver, then our library should degenerate to only log to the file. At this time, it can be used to check whether there is a driver, if it exists, create a log record to the database , otherwise create a log record to a file . JDBC
@ConditionalOnClass
JDBC
Bean
Bean
Click to follow and learn about Huawei Cloud's fresh technologies for the first time~
Clarification about MyBatis-Flex plagiarizing MyBatis-Plus Arc browser officially released 1.0, claiming to be a substitute for Chrome OpenAI officially launched Android version ChatGPT VS Code optimized name obfuscation compression, reduced built-in JS by 20%! LK-99: The first room temperature and pressure superconductor? Musk "purchased for zero yuan" and robbed the @x Twitter account. The Python Steering Committee plans to accept the PEP 703 proposal, making the global interpreter lock optional . The number of visits to the system's open source and free packet capture software Stack Overflow has dropped significantly, and Musk said it has been replaced by LLM