SpringBoot(三)

SpringBoot基礎

SpringBoot的核心功能

1.獨立運行的Spring項目 Spring Boot能夠以jar包的形式獨立運行,運行一個Spring Boot項目之須要經過java -jar xx.jar來運行。java

2.內嵌的Servlet容器 Spring Boot可選擇內嵌Tomcat,jetty或者Undertow,這樣咱們無需以war包形式部署項目。git

3.提供starter簡化Maven配置 Spring提供了一系列的starter pom來簡化Maven的依賴加載,例如加入了spring-boot-starter-web時,會自帶加入web開發須要的其餘jar包。github

4.自動配置Spring Spring Boot會根據在路徑中的jar包,類的=,爲jar包的類自動配置Bean,這樣會極大的減小咱們使用的配置。這樣在大多數狀況下均可以知足,可是在極少數的狀況下都須要咱們本身配置,此時就沒有提供支持,須要咱們自定義配置。web

5.準生產的應用監控 Spring Boot提供了基於http,ssh,telnet對運行時的項目進行監控。spring

6.無代碼生成和xml配置。安全

Spring 4.x提倡使用Java配置和註解配置組合,而Spring Boot不須要任何xml配置便可實現的全部配置.Spring4.x提供了條件註解,使得Spring Boot變的靈活。session

SpringBoot核心

基本配置

入口類和@SpringBootApplication

Spring Boot一般有一個名爲*Application的入口類,入口類裏面有一個main方法,這個main方法其實就是一個標準的Java應用入口方法。在main方法中使用SpringApplication.run(*Application.class,args),啓動SpringBootapp

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan(excludeFilters = {
		@Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class),
		@Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) })
public @interface SpringBootApplication {

從上面的源碼能夠知道@SpringBootApplication註解是一個組合註解,它組合了@EnableAutoConfiguration,@ComponentScan;經過使用這個組合註解咱們能夠省去本身配置的麻煩,可是咱們也能夠在啓動類上直接使用@SpringBootConfiguration,@EnableAutoConfiguration,@ComponentScan本身手動配置,其中@EnableAutoConfiguration會讓Spring Boot根據類路徑中的jar包依賴爲當前項目進行自動配置。框架

使用了@SpringBootApplication所在類的同級別包以及如下級包裏的Bean。通常狀況下獎入口類放置在groupId+arctifactId組合包名下.dom

使用xml配置

Spring Boot提倡零配置,即沒有xml配置,可是在實際項目中,可能有一些特殊要求必需要使用xml配置,這時咱們能夠經過Spring提供的@ImportResource來加載。

@ImportResource({"classpath:demo-context.xml","classpath:another-context.xml"})

常規屬性配置

在常規的Spring項目下,須要注入properties文件,而後再配置類裏面經過@PropertiySource指明properties文件的位置,而後使用@Value注入值,可是在Spring Boot裏面,只需在application.properties或者application.yml定義屬性,而後使用@Value直接注入便可。

類型安全的配置(基於properties)

上例中使用@Value注入每一個配置在實際項目中顯得格外的麻煩,由於咱們的配置一般會是許多個,若使用上例的方式則須要使用@Value注入屢次。 SpringBoot提供了基於類型安全的配置方式,經過@ConfigurationProperties獎properties屬性和一個Bean及屬性進行關聯,從而實現類型安全的配置。 例子:

application.yml(配置文件)

user:
  userName: zhangsan
  userAge: 28

UserConfig.java(配置類)

@Configuration
@ConfigurationProperties(prefix = "user")
public class UserConfig {
	private String userName;
	private String userAge;

	public String getUserName() {
		return userName;
	}

	public void setUserName(String userName) {
		this.userName = userName;
	}

	public String getUserAge() {
		return userAge;
	}

	public void setUserAge(String userAge) {
		this.userAge = userAge;
	}
}

在控制類引入配置類:

@Autowired
	UserConfig userConfig;

控制類調用配置類獲取屬性:

@RequestMapping("/getUserInfo_2")
	public String getInfo_2(){
		return "userName:"+userConfig.getUserName()+"-"+"userAge:"+userConfig.getUserAge();
	}

請求結果:

日誌配置

Spring Boot支持Java Util Logging,Log4J,Log4J2和Logback做爲日誌框架,不管使用哪一種日誌框架,SpringBoot都已經爲當前日誌框架的控制檯輸出以及文件作好了配置。默認狀況下Spring Boot使用Logbac做爲日誌框架。配置日誌級別:

例子:

Profile配置

Profile是Spring用來針對不一樣的環境對不一樣的配置提供支持,全局的Profile配置使用application-{profile}.yml或者application-{profile}.properties.在application中設置spring.profile.active=prod來指定得到的Profile.

如上圖所示,若是在application.yml中配置了spring.profiles.active=dev,那麼久使用dev的配置,配置了prod就使用prod的配置。

Spring Boot運行原理

Spring Boot關於自動配置的源碼在spring-boot-autoconfigure-x.jar內,主要的配置以下:

若是想知道Spring爲咱們左了那些自動配置,能夠經過三種方式查看當前項目中已開啓額和爲開啓的自動配置的報告。

1.運行jar時增長--debug java -jar xx.jar --debug

2.application.yml配置() debug=true

3.在STS中設置。

測試結果:

運做原理

關於Spring Boot的運行原理,這些都須要歸結到@SpringBootApplication註解上來,這個註解是一個組合註解,核心功能由@EnableAutoConfiguration註解提供的。

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan(excludeFilters = {
		@Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class),
		@Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) })
public @interface SpringBootApplication {

這個地方最重要的是@EnableAutoConfiguration註解,改註解內最爲重要的是@Import註解,AutoConfigurationImportSelector使用了SpringFactoriesLoader.loadFactoryNames()方法來掃面具備META-INF/spring.factories文件的jar包,而spring-boot-autoconfigure-x.jar恰好由這個spring.factories文件,此文件中聲明瞭又那些自動配置.

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@AutoConfigurationPackage
@Import(AutoConfigurationImportSelector.class)
public @interface EnableAutoConfiguration {

核心註解

在org.springframework.boot.autoconfigure.condition包下又以下的註解:

@ConditionalOnBean:當容器又知道的Bean的條件下 @ConditionalOnClass:當類路徑下又指定的類的條件下 @ConditionalOnCloudPlatform:這與指定的雲平臺處於活動狀態時匹配 @ConditionalOnExpression:基於SpEL表達式的條件下 @ConditionalOnJava:基於JVM版本做爲判斷條件. @ConditionalOnJndi:在jndi存在的條件下查找指定的位置 @ConditionalOnMissingBean:容器裏沒有指定的Bean的狀況下 @ConditionalOnMissingClass:當類路徑沒有指定的類的條件下 @ConditionalOnNotWebApplication:當前項目不在web項目的條件下 @ConditionalOnProperty:指定的屬性是否又指定的值 @ConditionalOnResource:類路徑下是否有指定的值。 @ConditionalOnSingleCandidate:當指定的Bean在容器中只有一個,或者雖然有多個可是指定首選的Bean. @ConditionalOnWebApplication:當前項目在Web項目的條件下.

private ConditionOutcome isWebApplication(ConditionContext context,
		AnnotatedTypeMetadata metadata, boolean required) {
	switch (deduceType(metadata)) {
	case SERVLET:
		return isServletWebApplication(context);
	case REACTIVE://springBoot2.0的WebFlux開發ReactiveWeb
		return isReactiveWebApplication(context);
	default:
		return isAnyWebApplication(context, required);
	}
}

private ConditionOutcome isServletWebApplication(ConditionContext context) {
		ConditionMessage.Builder message = ConditionMessage.forCondition("");
		//判斷GenericWebApplicationContext是否在類路徑中
		if (!ClassNameFilter.isPresent(SERVLET_WEB_APPLICATION_CLASS,
				context.getClassLoader())) {
			return ConditionOutcome.noMatch(
					message.didNotFind("servlet web application classes").atAll());
		}
		//容器是否有名爲session的scope
		if (context.getBeanFactory() != null) {
			String[] scopes = context.getBeanFactory().getRegisteredScopeNames();
			if (ObjectUtils.containsElement(scopes, "session")) {
				return ConditionOutcome.match(message.foundExactly("'session' scope"));
			}
		}
		//判斷當前容器的Enviromemt是否是ConfigurableWebEnvironment
		if (context.getEnvironment() instanceof ConfigurableWebEnvironment) {
			return ConditionOutcome
					.match(message.foundExactly("ConfigurableWebEnvironment"));
		}
		//當前的ResourceLoader是否爲WebApplicationContext(ResourceLoader是ApplicationContext的頂級接口之一)
		if (context.getResourceLoader() instanceof WebApplicationContext) {
			return ConditionOutcome.match(message.foundExactly("WebApplicationContext"));
		}
		//返回一個ConditionOutcome對象
		return ConditionOutcome.noMatch(message.because("not a servlet web application"));
	}

實現自動配置

HelloService.java(須要自動注入的bean)

public class HelloService {
	private String msg;

		public String getMsg() {
			return msg;
		}

		public void setMsg(String msg) {
			this.msg = msg;
		}
	}

HelloServiceProperties.java(類型安全的配置類)

@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;
		}
	}

HelloAutoConfiguration.java(自動配置類)

@Configuration//設置這是一個配置類
	@EnableConfigurationProperties(HelloServiceProperties.class)//
	@ConditionalOnClass(HelloService.class)
	@ConditionalOnProperty(prefix = "hello",value = "enabled",matchIfMissing = true)
	public class HelloAutoConfiguration {
		@Autowired
		HelloServiceProperties helloServiceProperties;

		@Bean
		@ConditionalOnMissingBean(HelloService.class)
		public HelloService helloService(){
			HelloService helloService = new HelloService();
			helloService.setMsg(helloServiceProperties.getMsg());
			return helloService;
		}
	}

除了上面的步驟以外還需在resources目錄下建立一個spring.factories文件,而且配置(\是換行,多個配置類使用逗號隔開):

org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.example.demo.config.HelloAutoConfiguration

啓動以後能夠看到:

項目地址:https://github.com/chenanddom/SpringBootOperationPrinciple

相關文章
相關標籤/搜索