Welcome to your attention
Increase in Competency and Waiting
Interview knowledge, job ready
Practice Exercise, Refuse 996
If this article is helpful and enjoyable to you, please give it a compliment!
Preface
Does it feel difficult to get promoted at work?
Do you find job interviews so difficult?
Do you feel like you are working overtime every day in 996?
You must maintain the ability to learn at work so that you can get a better promotion at work. The salary increase is just around the corner. You are welcome to study together.
In job-hunting interviews, we should summarize the interview knowledge points on the basis of learning. Jobs are also around the clock. You are welcome to study the Interview Knowledge, Job Waiting series together.
Finally, should we practice until we have enough theoretical knowledge?Welcome to the Learning [Practice, Reject 996] Series
One of the main manifestations of SpringBoot's convenience and speed is starter pom, which provides us with starter POM to simplify most scenarios for enterprise development. As long as the starter POM needed for application scenarios is used, only the corresponding starter can be introduced to get automatically configured beans provided by Spring Boot.
_However, there may be many cases where we need to customize the stater so that our internal systems can load the configuration automatically when they call the common configuration module.For example, many companies host passwords for production databases on another company's system that specifically manages production passwords. Each system needs to be used by the company when it needs to, and can now be configured in the form of starter automatic configuration.
1. SpringBoot Starter Source Analysis
What does the core comment @EnableAutoConfiguration comment in the Q:@SpringBootApplication comment do for starter?
@EnableAutoConfiguration Source Analysis:
@Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) @Documented @Inherited @AutoConfigurationPackage @Import(AutoConfigurationImportSelector.class) public @interface EnableAutoConfiguration { String ENABLED_OVERRIDE_PROPERTY = "spring.boot.enableautoconfiguration"; Class<?>[] exclude() default {}; String[] excludeName() default {}; }
_You can see from the source that the key feature is the @import annotation to import the AutoConfigurationImportSelector class, the main method getCandidateConfigurations() uses the SpringFactoriesLoader.loadFactoryNames() method to load a file of META-INF/spring.factories (spring.factories declares specific automatic configuration).
protected List<String> getCandidateConfigurations(AnnotationMetadata metadata, AnnotationAttributes attributes) { List<String> configurations = SpringFactoriesLoader.loadFactoryNames( getSpringFactoriesLoaderFactoryClass(), getBeanClassLoader()); Assert.notEmpty(configurations, "No auto configuration classes found in META-INF/spring.factories. If you " + "are using a custom packaging, make sure that file is correct."); return configurations; }
<br>
Q: Typically, starter s operate on conditions, such as creating different beans based on different conditions.What annotations are available in SpringBoot?
You can use the conditional annotations for org.springframwork.boot.autoconfigure.condition as follows:
annotation | analysis |
---|---|
@ConditionalOnBean | When there is a specified Bean in the container. |
@ConditionalOnClass | If there is a specified class under the class path. |
@ConditionalOnExpression | Based on the SpEL expression as the criterion. |
@ConditionalOnJava | Based on the JVM version as the criterion. |
@ConditionalOnJndi | Finds the specified location in the presence of JNDI. |
@ConditionalOnMissingBean | When no Bean is specified in the container. |
@ConditionalOnMissingClass | If there is no specified class under the class path. |
@ConditionalOnNotWebApplication | The current project is not a Web project. |
@ConditionalOnProperty | Whether the specified property has the specified value. |
@ConditionalOnResource | Whether the class path has a specified value. |
@ConditionalOnSingleCandidate | When a specified Bean is only one in a container, or if there are multiple beans, the preferred one is specified. |
@ConditionalOnWebApplicatio | The current project is a Web project. |
2. Custom starter
Here you will simulate a company getting a production password module to customize starter demo
2.1 Core Dependencies
<dependencyManagement> <dependencies> <dependency> <!-- Import dependency management from Spring Boot --> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-dependencies</artifactId> <version>2.1.5.RELEASE</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-autoconfigure</artifactId> </dependency> </dependencies>
2.2 Service class service and property configuration injection
PasswordService service class:
public class PasswordService { //key required for third-party systems to obtain passwords private String objectKey; @Autowired //Simulated third-party system service private ThirdPartySystemService thirdPartySystemService; public String getSystemPassword(String objectKey,String originalPassord){ if(StringUtils.isEmpty(objectKey)){ return originalPassord; } //Get passwords from third-party systems String password= thirdPartySystemService.getPassword(objectKey); //Return password return password!=null?password:originalPassord; } } //Analog third-party system service public class ThirdPartySystemService { public String getPassword(String objectKey){ //Returns a 32-bit random number return UUID.randomUUID().toString(); } }
Attribute Configuration Class:
//Get property values from the @ConfigurationProperties annotation @ConfigurationProperties(prefix = "project.starter") public class BaseServiceProperties { private String serviceName; private String serviceVersion; public String getServiceName() { return serviceName; } public void setServiceName(String serviceName) { this.serviceName = serviceName; } public String getServiceVersion() { return serviceVersion; } public void setServiceVersion(String serviceVersion) { this.serviceVersion = serviceVersion; } }
Configuration Attribute Use Class:
public class BaseStarterService { public void addServiceName(BaseServiceProperties baseServiceProperties){ System.out.println("serviceName:"+baseServiceProperties.getServiceName()+"----"+"serviceVersion"+baseServiceProperties.getServiceVersion()); } }
Other classes:
//Determine whether a windows system is available public class WindowsCondition implements Condition { private final static String WINDOWS="Windows"; /** * ConditionContext: Context (environment) in which conditions can be used * AnnotatedTypeMetadata: annotation */ public boolean matches(ConditionContext conditionContext, AnnotatedTypeMetadata annotatedTypeMetadata) { //Get the current environment variable Environment environment=conditionContext.getEnvironment(); //Get bean Registrar BeanDefinitionRegistry registry = conditionContext.getRegistry(); //Can get beanfactory used by ioc ConfigurableListableBeanFactory beanFactory = conditionContext.getBeanFactory(); //Get the operating system in the environment variable String property = environment.getProperty("os.name"); //Determine if the operating system is windows if(property.contains(WINDOWS)){ //Determine if the baseWindowsSevice class exists or register bean s if it does not exist boolean isWindowsSevice = registry.containsBeanDefinition("baseStarterService"); if(!isWindowsSevice){ //Specify Bean Definition Information; (Bean Type, Bean Series of Information) RootBeanDefinition beanDefinition = new RootBeanDefinition(BaseStarterService.class); //Register a Bean, specify the bean name registry.registerBeanDefinition("baseStarterService", beanDefinition); BaseStarterService windowsSevice = (BaseStarterService)beanFactory.getBean("baseStarterService"); } return true; } return false; } }
2.3 Automatic Configuration Class
Code Interpretation:
- @EnableConfiguration Properties: Read the properties of the configuration file
- @Import: Import other configuration or custom classes
- @Conditional: Register the class to determine if the current environment is windows
- @ConditionalOnProperty: Determines whether the property spring.project.ThirdPartySystemService.isPassword is equal to true or not registers the class if it is not true
- @ConditionalOnClass: Determines if the ThirdPartySystemService class exists in the IOC container, and creates a PasswordService bean if it exists
@Configuration //Automatically load profile property values @EnableConfigurationProperties(BaseServiceProperties.class) @Import(BeanConfiguration.class) //Determine if the current environment is windows @Conditional(WindowsCondition.class): //Determine if the attribute spring.project.ThirdPartySystemService.isPassword is equal to true @ConditionalOnProperty(prefix = "spring.project.ThirdPartySystemService",value = "enablePassword", havingValue = "true",matchIfMissing = true) public class AutoConfigurationPassoword { @Autowired private BaseServiceProperties baseServiceProperties; @Autowired private BaseStarterService baseWindowsService; //Loading third-party system service s @Bean("thirdPartySystemService") public ThirdPartySystemService thirdPartySystemService(){ baseWindowsService.addServiceName(baseServiceProperties); return new ThirdPartySystemService(); } @Bean //Determine if ThirdPartySystemService class exists in IOC container, create PasswordService bean if it exists @ConditionalOnClass(ThirdPartySystemService.class) public PasswordService passwordService(){ baseWindowsService.addServiceName(baseServiceProperties); return new PasswordService(); } }
2.4 Registration Configuration
_For automatic configuration to take effect, you need to register the automatic configuration class, that is, create a new METAINF/spring.factories under src/main/resources.In spring.factorie, the configuration is as follows:
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ com.cn.ccww.configuration.AutoConfigurationPassoword
If there are multiple autoconfigurations, separate them with','where'\' is used to read properties after line breaks.
3. Test custom starter
3.1 import dependency
<dependencies> <dependency> <artifactId>spring-boot-starter-base-service</artifactId> <groupId>com.cn.ccww</groupId> <version>1.0-SNAPSHOT</version> </dependency> </dependencies>
3.2 application.properties attribute
The application.properties file has a corresponding field to start a custom starter, and you can set the properties required by the starter.As follows:
//Custom Starter Configuration //Custom starter is not started when the value of this property is not true spring.project.ThirdPartySystemService.enablePassword=true project.starter.serviceName=ccww project.starter.serviceVersion=1.0
4. Summary
As described above, starter's general workflow is:
-
When SpringBoot starts, it automatically searches for JAR packages that contain the spring.factories file;
-
Load the AutoConfiguration class from the spring.factories file;
-
Load conditional (@ConditionalOnXxx) bean s into the Spring IOC container through the AutoConfiguration class;
-
Users can directly use bean s that are automatically loaded into IOC.
You are also welcome to pay attention to the G Z H [Ccww Notes], the first time original technical articles are available