springboot 1.5.3 源码分析(二):springboot自动化配置原理及自定义starter

欢迎关注本人公众号

在这里插入图片描述

springcloud系列学习笔记目录参见博主专栏 spring boot 2.X/spring cloud Greenwich。

前面的文章已经讲了springboot的实现原理,无非就是通过spring的condition条件实现的,还是比较简单的(感谢spring设计的开放性与扩展性)。
在实际工作过程中会遇到需要自定义starter的需求,那么我们接下来就自己实现一个starter。

先看一下目录结构:
springboot 1.5.3 源码分析(二):springboot自动化配置原理及自定义starter_第1张图片

  • MyConfig是自定义的配置类
  • HelloService是自定义的bean
  • HelloServiceProperties是自定义的类型安全的属性配置
  • MEYA-INF/spring.factories文件是springboot的工厂配置文件

本项目就是自定义的starter。假设我们这里需要一些配置项,使用者在使用该starter时,需要在application.properties文件中配置相关属性。这里我们使用了@ConfigurationProperties来将属性配置到一个POJO类中。这样做的好处是:可以检测数据的类型,并且可以对数据值进行校验,详情请参考我的另一篇博客:

HelloServiceProperties类内容如下:

import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;

/**
 * Created by hzliubenlong on 2017/12/13.
 */
@Data
@Component
@ConfigurationProperties(prefix = "hello")
public class HelloServiceProperties {
    private String a;
    private String b;
}

这样使用这个starter的时候,就可以配置hello.a=**来设置属性了。

HelloService是我们的bean,这里实现比较简单,获取外部的属性配置,打印一下日志。内容如下:


/**
 * Created by hzliubenlong on 2017/12/12.
 */
@Slf4j
public class HelloService {

    String initVal;

    public void setInitVal(String initVal) {
        this.initVal = initVal;
    }

    public String getInitVal() {
        return initVal;
    }

    public String hello(String name) {
        log.info("initVal={}, name={}", initVal, name);
        return "hello " + name;
    }

}

接下来是比较重要的配置类MyConfig,前面已经讲过,springboot是通过条件注解来判断是否要加载bean的,这些内容都是在我们自定义的配置类中来实现:

import com.example.myservice.HelloService;
import com.example.properties.HelloServiceProperties;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
@EnableConfigurationProperties(HelloServiceProperties.class)
public class MyConfig {

    @Autowired
    private HelloServiceProperties helloServiceProperties;

    @ConditionalOnProperty(prefix="hello", value="enabled", matchIfMissing = true)
    @ConditionalOnClass(HelloService.class)
    @Bean
    public HelloService initHelloService() {
        HelloService helloService = new HelloService();
        helloService.setInitVal(helloServiceProperties.getA());
        return helloService;
    }
}

@Configuration表明这是一个配置类
@EnableConfigurationProperties(HelloServiceProperties.class)表示该类使用了属性配置类HelloServiceProperties
initHelloService()方法就是实际加载初始化helloServicebean的方法了,它上面有三个注解:

  1. @ConditionalOnProperty(prefix="hello", value="enabled", matchIfMissing = true): hello.enabled=true时才加载这个bean,配置没有的话,默认为true,也就是只要引入了这个依赖,不做任何配置,这个bean默认会加载。
  2. @ConditionalOnClass(HelloService.class):当HelloService这个类存在时才加载bean。
  3. @Bean:表明这是一个产生bean的方法,改方法生成一个HelloService的bean,交给spring容器管理。

好了,到这里,我们的代码已经写完。根据前面讲的springboot的原理我们知道,springboot是通过扫描MEYA-INF/spring.factories这个工厂配置文件来加载配置类的, 所以我们还需要创建这个文件。其内容如下:

org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.example.demo.MyConfig

上面的\是换行符,只是为了便于代码的阅读。通过这个文件,springboot就可以读取到我们自定义的配置类MyConfig。
接下来我们只需要打个jar包即可供另外一个项目使用了。下面贴一下pom.xml的内容:



	4.0.0

	com.example
	springboot-starter-hello
	0.0.1-SNAPSHOT
	jar

	springboot-starter-hello
	Demo project for Spring Boot

	
		org.springframework.boot
		spring-boot-starter-parent
		1.5.3.RELEASE
		 
	

	
		
			org.springframework.boot
			spring-boot-starter-web
		

		
			org.projectlombok
			lombok
			true
		
		
			org.springframework.boot
			spring-boot-starter-test
			test
		
	

	
		
			
				maven-release-plugin
				2.4.2
				
					
						org.apache.maven.scm
						maven-scm-provider-gitexe
						1.8.1
					
				
			
			
				org.apache.maven.plugins
				maven-compiler-plugin
				3.3
				
					1.8
					1.8
					UTF-8
				
			
			
				org.apache.maven.plugins
				maven-surefire-plugin
				2.19.1
				
					false
				
			
			
				org.apache.maven.plugins
				maven-resources-plugin
				2.7
				
					UTF-8
				
			
			
				org.apache.maven.plugins
				maven-source-plugin
				
					
						attach-sources
						
							jar
						
					
				
			
			
				org.apache.maven.plugins
				maven-jar-plugin
				2.4
				
					
						
							true
						
					
				
			
		
	



上面定义了一个starter,下面我们将写一个新的工程,来引用我们自定义的starter。还是先看一下项目目录:
springboot 1.5.3 源码分析(二):springboot自动化配置原理及自定义starter_第2张图片
要想引用我们自定义的starter,自然是先引入依赖了:


            com.example
            springboot-starter-hello
            0.0.1-SNAPSHOT
		

然后再application.properties文件中添加如下配置:

hello.enabled=true
hello.a=hahaha

好了,现在就可以在项目中注入HelloService使用了。是的,就是那么简单.DemoApplication主类如下:

import com.example.demo.environment.EnvironmentService;
import com.example.myservice.HelloService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@Slf4j
@SpringBootApplication
public class DemoApplication {

	@Autowired
	HelloService helloService;

	@RequestMapping("/")
	public String word(String name) {
        return helloService.hello(name);
	}
	
	public static void main(String[] args) {
		SpringApplication.run(DemoApplication.class, args);
	}
}

启动项目,访问URLhttp://127.0.0.1:8080/?name=hhh:
这里写图片描述
后台打印日志为initVal=hahaha, name=hhh其中hahaha就是我们没在配置文件中配置的属性值,这句日志是我们上面starter项目中com.example.myservice.HelloService#hello方法打印出来的。

end。

springcloud系列学习笔记目录参见博主专栏 spring boot 2.X/spring cloud Greenwich。

你可能感兴趣的:(spring,boot,2.X/spring,cloud,Greenwich)