SpringBoot 學(xué)習(xí)——運(yùn)行原理學(xué)習(xí)及自定義 Starter pom
SpringBoot學(xué)習(xí)——運(yùn)行原理學(xué)習(xí)及自定義Starter pom
運(yùn)行原理
SpringBoot最大的特點(diǎn)就是提供了很多默認(rèn)的配置,該能力就是通過Spring4.x提供了基于條件來配置Bean的能力這一原理來實(shí)現(xiàn)的。
那么我們?nèi)绾蝸韺?shí)現(xiàn)一個(gè)自定義的starter呢
自定義Starter pom
新建一個(gè)maven項(xiàng)目
參考SpringBoot學(xué)習(xí)——SpringBoot入門HelloWorld
總目錄結(jié)構(gòu)
修改pom.xml,添加相關(guān)依賴
4.0.0
com.pzr
spring-boot-starter-pzrhello
0.0.1-SNAPSHOT
org.springframework.boot
spring-boot-starter-parent
1.5.1.RELEASE
org.springframework.boot
spring-boot-autoconfigure
org.springframework.boot
spring-boot-starter-web
添加屬性配置類
package com.pzr.spring_boot_stater_pzrhello;
import org.springframework.boot.context.properties.ConfigurationProperties;
/**
* 屬性配置類
* @author pzr
*
*/
@ConfigurationProperties(prefix="hello")
public class HelloServiceProperties {
private static final String MSG = "world";
private String msg = MSG;
public String getMsg() {
return msg;
}
public void setMsg(String msg) {
this.msg = msg;
}
}
代碼說明:
使用@ConfigurationProperties注解來設(shè)置前綴,在application中通過hello.msg=來設(shè)置,若不設(shè)置,默認(rèn)為hello.msg=world。
添加判斷依據(jù)類
package com.pzr.spring_boot_stater_pzrhello;
/**
* 判斷依據(jù)類
* @author pzr
*
*/
public class HelloService {
private String msg;
public String sayHello(){
return "Hello "+msg;
}
public String getMsg() {
return msg;
}
public void setMsg(String msg) {
this.msg = msg;
};
}
代碼說明
通過此類來調(diào)用msg,進(jìn)行打印。
添加自動(dòng)配置類
package com.pzr.spring_boot_stater_pzrhello;
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;
/**
* 自動(dòng)配置類
* @author pzr
*
*/
@Configuration
@EnableConfigurationProperties(HelloServiceProperties.class)
@ConditionalOnClass(HelloService.class)
@ConditionalOnProperty(prefix="hello",value="enabled",matchIfMissing=true)
public class HelloServiceAutoConfiguration {
@Autowired
private HelloServiceProperties helloServiceProperties;
@Bean
public HelloService helloService(){
HelloService helloService = new HelloService();
helloService.setMsg(helloServiceProperties.getMsg());
return helloService;
}
}
代碼說明
- @Configuration:使用該注解來說明該類是配置類,等價(jià)于xml中的beans
- @EnableConfigurationProperties(HelloServiceProperties.class):開啟屬性注入,對注解配置Bean的支持
- @ConditionalOnClass(HelloService.class):條件注解,當(dāng)類路徑下有指定的類的條件下。
- @ConditionalOnProperty(prefix="hello",value="enabled",matchIfMissing=true):條件注解,指定的屬性是否有指定的值。當(dāng)設(shè)置hello=enabled,如果沒有設(shè)置則默認(rèn)為true,即為條件符合。假如我們將matchIfMissing設(shè)置為false,則當(dāng)設(shè)置hello=enabled時(shí),條件為false,則不會(huì)將該Bean加載進(jìn)容器類,當(dāng)使用@Autowired注入HelloService時(shí)會(huì)報(bào)錯(cuò)。
org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'com.pzr.spring_boot_stater_pzrhello.HelloService' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)} - @Autowired:將屬性配置類注入進(jìn)來。
- @Bean:使用Java配置的方式來配置這個(gè)類,等價(jià)于xml中的bean。
- @ConditionalOnMissingBean(HelloService.class):容器中沒有這個(gè)Bean時(shí),新建這個(gè)Bean。
注冊配置
在src/main/resource下新建META-INFO/spring.factories文件。該文件可在spring-boot-1.5.1.RELEASE\spring-boot-autoconfigure\src\main\resources\META-INF下找到。
個(gè)人的只需要設(shè)置如下即可:
# Auto Configure
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.pzr.spring_boot_stater_pzrhello.HelloServiceAutoConfiguration
如果有多個(gè),逗號(hào)分隔即可,如下:
# Auto Configure
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
org.springframework.boot.autoconfigure.admin.SpringApplicationAdminJmxAutoConfiguration,\
org.springframework.boot.autoconfigure.aop.AopAutoConfiguration,\
org.springframework.boot.autoconfigure.amqp.RabbitAutoConfiguration
同項(xiàng)目下使用
添加主方法
在當(dāng)前項(xiàng)目下,添加MainApplication.java,用于測試之前寫的starter是否成功
package com.pzr.spring_boot_stater_pzrhello;
import org.springframework.beans.factory.annotation.Autowired;
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
@SpringBootApplication
public class MainApplication {
@Autowired
HelloService helloService;
@RequestMapping("/")
public String index(){
return helloService.sayHello();
}
public static void main(String[] args){
SpringApplication.run(MainApplication.class, args);
}
}
添加application.properties
在src/main/resources下添加application.properties配置文件
debug=true
hello.msg=1231231
debug是為了看到啟動(dòng)日志
hello.msg是我們自定義的打印內(nèi)容
啟動(dòng)項(xiàng)目
結(jié)果如下:
打包使用
將項(xiàng)目打包并發(fā)到本地庫
右鍵項(xiàng)目-->Run as-->Maven build..
輸入clean install發(fā)到本地庫
新建一個(gè)maven項(xiàng)目
修改pom文件
4.0.0
HelloConsumer
HelloConsumer
0.0.1-SNAPSHOT
org.springframework.boot
spring-boot-starter-parent
1.5.1.RELEASE
org.springframework.boot
spring-boot-maven-plugin
org.apache.maven.plugins
maven-jar-plugin
true
com.pzr.consumer.test.OfficialDemo
org.springframework.boot
spring-boot-starter-web
com.pzr
spring-boot-starter-pzrhello
0.0.1-SNAPSHOT
其中spring-boot-starter-pzrhello是我們剛剛打的包
添加MainApplication.java文件
package com.pzr.springbootautoconfig;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.pzr.spring_boot_stater_pzrhello.HelloService;
@RestController
@ComponentScan(basePackages={"com.pzr"})
@SpringBootApplication
public class MainApplication {
@Autowired
HelloService helloService;
@RequestMapping("/")
public String index(){
return helloService.sayHello();
}
public static void main(String[] args){
SpringApplication.run(MainApplication.class, args);
}
}
注意:如果不設(shè)置@ComponentScan(basePackages={"com.pzr"}) ,則會(huì)掃描不到com.pzr.spring_boot_stater_pzrhello下的bean,只會(huì)默認(rèn)掃描所在類包下的所有目錄。
添加application.properties
debug=true
hello.msg=pzrmsg
運(yùn)行查看效果
從結(jié)果可以看出雖然spring-boot-starter-pzrhello包里也有application.properties文件,但是最終使用的是新項(xiàng)目中的application.properties文件的設(shè)置。
問題
- 無論我設(shè)不設(shè)置@ConditionalOnMissingBean(HelloService.class),bean都會(huì)加載。
- 無論我在不在spring.factories中添加HelloServiceAutoConfiguration,配置都會(huì)生效。
- 在jar包使用時(shí),如果不設(shè)置@ComponentScan(basePackages={"com.pzr"})將會(huì)報(bào)錯(cuò),找不到bean。給注解是設(shè)置掃描位置的,可設(shè)置多個(gè)。
org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'com.pzr.spring_boot_stater_pzrhello.HelloService' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)}最近將會(huì)繼續(xù)學(xué)習(xí)springboot,如果有大神能看到這篇筆記,希望能不吝賜教。
