springcloud系列学习笔记目录参见博主专栏 spring boot 2.X/spring cloud Greenwich。
前面的文章已经讲了springboot的实现原理,无非就是通过spring的condition条件实现的,还是比较简单的(感谢spring设计的开放性与扩展性)。
在实际工作过程中会遇到需要自定义starter的需求,那么我们接下来就自己实现一个starter。
MyConfig
是自定义的配置类HelloService
是自定义的beanHelloServiceProperties
是自定义的类型安全的属性配置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()
方法就是实际加载初始化helloService
bean的方法了,它上面有三个注解:
@ConditionalOnProperty(prefix="hello", value="enabled", matchIfMissing = true)
: hello.enabled=true
时才加载这个bean,配置没有的话,默认为true,也就是只要引入了这个依赖,不做任何配置,这个bean默认会加载。@ConditionalOnClass(HelloService.class)
:当HelloService这个类存在时才加载bean。@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
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。还是先看一下项目目录:
要想引用我们自定义的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。