SpringBoot自动配置原理

配置文件到底能写什么?怎么写?

SpringBoot官方文档 :https://docs.spring.io/spring-boot/docs/2.2.5.RELEASE/reference/htmlsingle/

分析自动配置原理

我们以HttpEncodingAutoConfiguration(Http编码自动配置)为例解释自动配置原理;

//表示这是一个配置类,和以前编写的配置文件一样,也可以给容器中添加组件
@Configuration(proxyBeanMethods = false)
//启动指定类的ConfigurationProperties功能;    
//进入这个HttpProperties查看,将配置文件中对应的值和HttpProperties绑定起来;    
/并把HttpProperties加入到ioc容器中

@EnableConfigurationProperties(ServerProperties.class)

//Spring底层@Conditional注解    
//根据不同的条件判断,如果满足指定的条件,整个配置类里面的配置就会生效;    
//这里的意思就是判断当前应用是否是web应用,如果是,当前配置类生效
@ConditionalOnWebApplication(type = ConditionalOnWebApplication.Type.SERVLET)

//判断当前项目有没有这个类CharacterEncodingFilter;SpringMVC中进行乱码解决的过滤器;
@ConditionalOnClass(CharacterEncodingFilter.class)

//判断配置文件中是否存在某个配置:spring.http.encoding.enabled;    
//如果不存在,判断也是成立的    
//即使我们配置文件中不配置pring.http.encoding.enabled=true,也是默认生效的
@ConditionalOnProperty(prefix = "server.servlet.encoding", value = "enabled", matchIfMissing = true)
public class HttpEncodingAutoConfiguration {

//他已经和SpringBoot的配置文件映射了 
	private final Encoding properties;

  //只有一个有参构造器的情况下,参数的值就会从容器中拿 
	public HttpEncodingAutoConfiguration(ServerProperties properties) {
		this.properties = properties.getServlet().getEncoding();
	}

//给容器中添加一个组件,这个组件的某些值需要从properties中获取 
	@Bean
	@ConditionalOnMissingBean//判断容器没有这个组件? 
	public CharacterEncodingFilter characterEncodingFilter() {
		CharacterEncodingFilter filter = new OrderedCharacterEncodingFilter();
		filter.setEncoding(this.properties.getCharset().name());
		filter.setForceRequestEncoding(this.properties.shouldForce(Encoding.Type.REQUEST));
		filter.setForceResponseEncoding(this.properties.shouldForce(Encoding.Type.RESPONSE));
		return filter;
	}

	@Bean
	public LocaleCharsetMappingsCustomizer localeCharsetMappingsCustomizer() {
		return new LocaleCharsetMappingsCustomizer(this.properties);
	}

	static class LocaleCharsetMappingsCustomizer
			implements WebServerFactoryCustomizer<ConfigurableServletWebServerFactory>, Ordered {

		private final Encoding properties;

		LocaleCharsetMappingsCustomizer(Encoding properties) {
			this.properties = properties;
		}

		@Override
		public void customize(ConfigurableServletWebServerFactory factory) {
			if (this.properties.getMapping() != null) {
				factory.setLocaleCharsetMappings(this.properties.getMapping());
			}
		}

		@Override
		public int getOrder() {
			return 0;
		}

	}

}

一句话总结 : 根据当前不同的条件判断,决定这个配置类是否生效!

  • 一但这个配置类生效;这个配置类就会给容器中添加各种组件;
  • 这些组件的属性是从对应的properties类中获取的,这些类里面的每一个属性又是和配置文件绑定 的;
  • 所有在配置文件中能配置的属性都是在xxxxProperties类中封装着;
  • 配置文件能配置什么就可以参照某个功能对应的这个属性类
//从配置文件中获取指定的值和bean的属性进行绑定 
@ConfigurationProperties(prefix = "spring.http") 
public class HttpProperties {    // ..... }

我们去配置文件里面试试前缀,看提示!
SpringBoot自动配置原理_第1张图片
这就是自动装配的原理!

精髓

1、SpringBoot启动会加载大量的自动配置类
2、我们看我们需要的功能有没有在SpringBoot默认写好的自动配置类当中;
3、我们再来看这个自动配置类中到底配置了哪些组件;(只要我们要用的组件存在在其中,我们就不需 要再手动配置了)
4、给容器中自动配置类添加组件的时候,会从properties类中获取某些属性。我们只需要在配置文件中 指定这些属性的值即可;

  • xxxxAutoConfigurartion:自动配置类;给容器中添加组件
  • xxxxProperties:封装配置文件中相关属性

了解:@Conditional

了解完自动装配的原理后,我们来关注一个细节问题,自动配置类必须在一定的条件下才能生效;

@Conditional派生注解(Spring注解版原生的@Conditional作用)
作用:必须是@Conditional指定的条件成立,才给容器中添加组件,配置配里面的所有内容才生效;
SpringBoot自动配置原理_第2张图片
那么多的自动配置类,必须在一定的条件下才能生效;也就是说,我们加载了这么多的配置类,但不是 所有的都生效

我们怎么知道哪些自动配置类生效?

我们可以通过启用 debug=true属性;来让控制台打印自动配置报告,这样我们就可以很方便的知道哪 些自动配置类生效

#开启springboot的调试类 
debug=true
  • Positive matches:(自动配置类启用的:正匹配)
  • Negative matches:(没有启动,没有匹配成功的自动配置类:负匹配)
  • Unconditional classes: (没有条件的类)

自定义starter

说明:
启动器模块是一个 空 jar 文件,仅提供辅助性依赖管理,这些依赖可能用于自动装配或者其他类库;

命名归约:
官方命名:

  • 前缀: spring-boot-starter-xxx
  • 比如:spring-boot-starter-web…

自定义命名:

  • xxx-spring-boot-starter
  • 比如:mybatis-spring-boot-starter

编写启动器

1、在IDEA中新建一个空项目 spring-boot-starter-diy
2、新建一个普通Maven模块:kuang-spring-boot-starter
SpringBoot自动配置原理_第3张图片
3、新建一个Springboot模块:kuang-spring-boot-starter-autoconfigure

SpringBoot自动配置原理_第4张图片
4、点击apply即可,基本结构
SpringBoot自动配置原理_第5张图片
5、在我们的 starter 中 导入 autoconfigure 的依赖!

 
<dependencies>    
    
<dependency>        
	<groupId>com.kuanggroupId>        
	<artifactId>kuang-spring-boot-starter-autoconfigureartifactId>        
	<version>0.0.1-SNAPSHOTversion>    
	dependency> 
dependencies>

6、将 autoconfigure 项目下多余的文件都删掉,Pom中只留下一个 starter,这是所有的启动器基本配 置
SpringBoot自动配置原理_第6张图片
7、我们编写一个自己的服务

package com.kuang;
public class HelloService {
    HelloProperties helloProperties;
    
    public HelloProperties getHelloProperties() {        
    	return helloProperties;    
    }
    public void setHelloProperties(HelloProperties helloProperties) {        
    	this.helloProperties = helloProperties;    
    }
     public String sayHello(String name){        
    	 return helloProperties.getPrefix() + name + helloProperties.getSuffix();    
     }
}

8、编写HelloProperties 配置类

package com.kuang;
import org.springframework.boot.context.properties.ConfigurationProperties;
// 前缀 kuang.hello 
@ConfigurationProperties(prefix = "kuang.hello") 
public class HelloProperties {
    private String prefix;    
    private String suffix;
    public String getPrefix() {        
    	return prefix;    
    }
    public void setPrefix(String prefix) {        
    	this.prefix = prefix;    
    }
    public String getSuffix() {        
    	return suffix;    
    }
    public void setSuffix(String suffix) {        
   		 this.suffix = suffix;    
    } 
 }

9、编写我们的自动配置类并注入bean,测试!

package com.kuang;
import org.springframework.beans.factory.annotation.Autowired; 
import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication ; 
import org.springframework.boot.context.properties.EnableConfigurationProperties; 
import org.springframework.context.annotation.Bean; 
import org.springframework.context.annotation.Configuration;

@Configuration 
@ConditionalOnWebApplication //web应用生效 
@EnableConfigurationProperties(HelloProperties.class) 
public class HelloServiceAutoConfiguration {
    @Autowired    
    HelloProperties helloProperties
      @Bean    
      public HelloService helloService(){       
      
      HelloService service = new HelloService();        			
      service.setHelloProperties(helloProperties);        
       return service;    
       }
}

10、在resources编写一个自己的META-INF\spring.factories

# Auto Configure 
org.springframework.boot.autoconfigure.EnableAutoConfiguration=com.kuang.HelloServiceAutoConfiguration

11、编写完成后,可以安装到maven仓库中!
SpringBoot自动配置原理_第7张图片

新建项目测试我们自己的写的启动器

1、新建一个SpringBoot 项目
2、导入我们自己写的启动器

<dependency>    
	<groupId>com.kuanggroupId>    
	<artifactId>kuang-spring-boot-starterartifactId>    
	<version>1.0-SNAPSHOTversion> 
dependency>

3、编写一个 HelloController 进行测试我们自己的写的接口!

package com.kuang.controller;
@RestController 
public class HelloController {
    @Autowired
     HelloService helloService;
    @RequestMapping("/hello")    
    public String hello(){        
    	return helloService.sayHello("zxc");    
    }
}

4、编写配置文件 application.properties

ang.hello.prefix="ppp" 
kuang.hello.suffix="sss"

5、启动项目进行测试,结果成功 !
SpringBoot自动配置原理_第8张图片

你可能感兴趣的:(G_互联网分布式技术,#,G1_SpringBoot,spring,boot,java)