[Practice Exercise, Reject 996]-SpringBoot 2.x Custom Spring boot Starter

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

Keywords: Spring Windows SpringBoot Attribute

Added by chetanrakesh on Sun, 17 Nov 2019 03:49:35 +0200