# SpringBoot 自动装配

Posted 爱码代码的喵

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了# SpringBoot 自动装配相关的知识,希望对你有一定的参考价值。

SpringBoot 自动装配

  • 传统的Spring项目会有很多的配置文件,比如我们要使用Redis,一般除了对应的依赖的jar包我们还需要在application.xml里面配置JedisConnectionFactoryJedisPoolConfigRedisTemplate。但是如果使用SpringBoot的话,系统会根据pom.xml里面的jar包,自动生成这些类并且注入到IOC容器当中。

自动装配的过程

  • SpringApplication.run(Application.class, args)在运行时,会读取spring-boot-autoconfigure.jar里面的spring.factories配置文件,配置文件中有所有自动装配类的配置类的className,然后生成对应功能的Configuration类,这些功能配置类要生效的话,会去classpath中找是否有该类的依赖类(也就是pom.xml必须有对应功能的jar包才行),然后配置类里再通过判断生成最后的功能类,并且配置类里面注入了默认属性值类,功能类可以引用并赋默认值。生成功能类的原则是自定义优先,没有自定义时才会使用自动装配类。

  • 要想自动装配一个类需要满足2个条件:

    • spring.factories里面有这个类的配置类(一个配置类可以创建多个围绕该功能的依赖类)
    • pom.xml里面需要有对应的jar
  • 整个过程的结果是两件事情:

    • 根据各种判断和依赖,最终生成了业务需要的类并且注入到IOC容器当中了
    • 自动装配生成的类赋予了一些默认的属性值

SpringBootApplication注解

  • EnableAutoConfiguration代表开启springboot的自动装配
  • @ComponentScan的功能其实就是自动扫描并加载符合条件的组件或bean定义,最终将这些bean定义加载到容器中
  • @Configuration注解这个注解实际上就是代表了一个配置类
@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注解

  • @EnableAutoConfigurationSpringboot应用启动自动装配的功能(包括加载对应的BeanIOC容器中,且根据默认配置对属性赋值)
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@AutoConfigurationPackage
@Import(AutoConfigurationImportSelector.class)
public @interface EnableAutoConfiguration 
  • @Import(AutoConfigurationImportSelector.class),可以帮助SpringBoot应用将所有符合条件的@Configuration配置都加载到当前SpringBoot创建并使用的IoC容器。同时借助于Spring框架原有的一个工具类:SpringFactoriesLoader

  • @EnableAutoConfiguration作用就是从classpath中搜寻所有的META-INF/spring.factories配置文件,并将其中org.springframework.boot.autoconfigure对应的配置项通过反射(Java Refletion)实例化为对应的标注了@ConfigurationJavaConfig形式的IoC容器配置类,然后汇总为一个bean加载到IoC容器

RedisTemplate 的自动配置

  • spring-boot-autoconfigure.jar/META-INF/spring.factories中获取默认功能配置类
org.springframework.boot.autoconfigure.web.client.RestTemplateAutoConfiguration=
  • RestTemplateAutoConfiguration配置类生效的一个条件是RestTemplate.class所以会去classpath下去查找对应的class文件
  • RestTemplateAutoConfiguration
@Configuration(proxyBeanMethods = false)
@AutoConfigureAfter(HttpMessageConvertersAutoConfiguration.class)
@ConditionalOnClass(RestTemplate.class)
@Conditional(NotReactiveWebApplicationCondition.class)
public class RestTemplateAutoConfiguration 
    
	@Bean
	@Lazy
	@ConditionalOnMissingBean
	public RestTemplateBuilderConfigurer restTemplateBuilderConfigurer(
			ObjectProvider<HttpMessageConverters> messageConverters,
			ObjectProvider<RestTemplateCustomizer> restTemplateCustomizers,
			ObjectProvider<RestTemplateRequestCustomizer<?>> restTemplateRequestCustomizers) 
		RestTemplateBuilderConfigurer configurer = new RestTemplateBuilderConfigurer();
		configurer.setHttpMessageConverters(messageConverters.getIfUnique());
		configurer.setRestTemplateCustomizers(restTemplateCustomizers.orderedStream().collect(Collectors.toList()));
		configurer.setRestTemplateRequestCustomizers(
				restTemplateRequestCustomizers.orderedStream().collect(Collectors.toList()));
		return configurer;
	

	@Bean
	@Lazy
	@ConditionalOnMissingBean
	public RestTemplateBuilder restTemplateBuilder(RestTemplateBuilderConfigurer restTemplateBuilderConfigurer) 
		RestTemplateBuilder builder = new RestTemplateBuilder();
		return restTemplateBuilderConfigurer.configure(builder);
	

	static class NotReactiveWebApplicationCondition extends NoneNestedConditions 

		NotReactiveWebApplicationCondition() 
			super(ConfigurationPhase.PARSE_CONFIGURATION);
		

		@ConditionalOnWebApplication(type = Type.REACTIVE)
		private static class ReactiveWebApplication 
            
		
	

  • RedisAutoConfiguration
@Configuration(proxyBeanMethods = false)
@ConditionalOnClass(RedisOperations.class)
@EnableConfigurationProperties(RedisProperties.class)
@Import( LettuceConnectionConfiguration.class, JedisConnectionConfiguration.class )
public class RedisAutoConfiguration 

	@Bean
	@ConditionalOnMissingBean(name = "redisTemplate")
	@ConditionalOnSingleCandidate(RedisConnectionFactory.class)
	public RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) 
		RedisTemplate<Object, Object> template = new RedisTemplate<>();
		template.setConnectionFactory(redisConnectionFactory);
		return template;
	

	@Bean
	@ConditionalOnMissingBean
	@ConditionalOnSingleCandidate(RedisConnectionFactory.class)
	public StringRedisTemplate stringRedisTemplate(RedisConnectionFactory redisConnectionFactory) 
		return new StringRedisTemplate(redisConnectionFactory);
	

相关注解

  • @ConditionalOnProperty:如果有指定的配置,条件生效;
  • @ConditionalOnBean:如果有指定的Bean,条件生效;
  • @ConditionalOnMissingBean:如果没有指定的Bean,条件生效;
  • @ConditionalOnMissingClass:如果没有指定的Class,条件生效;
  • @ConditionalOnWebApplication:在Web环境中条件生效;
  • @ConditionalOnExpression:根据表达式判断条件是否生效。

@ConditionalOnMissingBean

  • @ConditionalOnMissingBean,它是修饰bean的一个注解,主要实现的是,当你的bean被注册之后,如果注册相同类型的bean,就不会成功,它会保证你的bean只有一个,即你的实例只有一个,当你注册多个相同的bean时,会出现异常,以此来告诉开发人员。

  • 对于自定义的配置类,我们应该加上@ConditionalOnMissingBean注解,以避免多个配置同时注入的风险。

@ConditionalOnBean

  • 判断当前需要注册的bean的实现类否被spring管理,如果被管理则注入,反之不注入
  • condition2注册的时候发现有condition1那么就不会注册
@Configuration
public class CustomConditionOnBean 

    private static final Logger looger = LoggerFactory.getLogger(CustomConditionOnBean.class);

    @Bean(name = "condition1")
    public ConditionTestBean getConditionBean2() 
        ConditionTestBean conditionTestBean = new ConditionTestBean();
        conditionTestBean.setId("2");
        conditionTestBean.setName("Condition12");
        looger.info("conditionTestBean2 注册了...");
        return conditionTestBean;
    
	
    @Bean(name = "condition2")
    @ConditionalOnMissingBean(name = "condition1")
    public ConditionTestBean getConditionBean1() 
        ConditionTestBean conditionTestBean = new ConditionTestBean();
        conditionTestBean.setId("1");
        conditionTestBean.setName("Condition1");
        looger.info("conditionTestBean1 注册了...");
        return conditionTestBean;
    


以上是关于# SpringBoot 自动装配的主要内容,如果未能解决你的问题,请参考以下文章

spring boot自动装配原理@EnableAutoConfiguration

springboot自动装配

Spring Boot核心特性之组件自动装配

关于 Spring Boot 自动装配你知道多少?

Spring boot 自动装配

Spring boot 自动装配