SpringBoot高级篇

今天的博客主题

       SpringBoot ——》SpringBoot高级篇


springBoot的自动装配原理

AutoConfigurationImportSelector.class 究竟做了什么?

public class AutoConfigurationImportSelector 
    implements DeferredImportSelector, BeanClassLoaderAware,
    ResourceLoaderAware, BeanFactoryAware, EnvironmentAware, Ordered {
    ....
}

DeferredImportSelector 继承了 ImportSelector。ImportSelector应该还有印象吧。

AutoConfigurationImportSelector 类 selectImports() 方法。

@Override
public String[] selectImports(AnnotationMetadata annotationMetadata) {
   if (!isEnabled(annotationMetadata)) {
      return NO_IMPORTS;
   }
   AutoConfigurationMetadata autoConfigurationMetadata = AutoConfigurationMetadataLoader
         .loadMetadata(this.beanClassLoader);
   AutoConfigurationEntry autoConfigurationEntry = getAutoConfigurationEntry(autoConfigurationMetadata,
         annotationMetadata);
   // 返回最终要加载的配置类
   return StringUtils.toStringArray(autoConfigurationEntry.getConfigurations());
}

getAutoConfigurationEntry() 方法:

protected AutoConfigurationEntry getAutoConfigurationEntry(AutoConfigurationMetadata autoConfigurationMetadata,
      AnnotationMetadata annotationMetadata) {
   if (!isEnabled(annotationMetadata)) {
      return EMPTY_ENTRY;
   }
   AnnotationAttributes attributes = getAttributes(annotationMetadata);
   // 获取候选配置类
   List<String> configurations = getCandidateConfigurations(annotationMetadata, attributes);
   // 移除重复配置类
   configurations = removeDuplicates(configurations);
   Set<String> exclusions = getExclusions(annotationMetadata, attributes);
   checkExcludedClasses(configurations, exclusions);
   configurations.removeAll(exclusions);
   configurations = filter(configurations, autoConfigurationMetadata);
   fireAutoConfigurationImportEvents(configurations, exclusions);
   return new AutoConfigurationEntry(configurations, exclusions);
}

主要是扫描spring-boot-autoconfigure\2.2.2.RELEASE\spring-boot-utoconfigure2.2.2.RELEASE.jar!

META-INF\spring.factories 中 EnableAutoConfiguration 对应的全类名

# 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,\
org.springframework.boot.autoconfigure.batch.BatchAutoConfiguration,\
org.springframework.boot.autoconfigure.cache.CacheAutoConfiguration,\
org.springframework.boot.autoconfigure.cassandra.CassandraAutoConfiguration,\
......

这些 xxxAutoConfiguration 都是一个个的自动配置类。

那这些自动配置类是如何工作的呢?

我们还是用 RedisAutoConfiguration 来分析下

// 标识是一个自动配置类
@Configuration(proxyBeanMethods = false)
// 判断当前环境中是否有这个类
@ConditionalOnClass(RedisOperations.class)
// 启动指定类的配置功能。并把配置文件中的属性和RedisProperties进行映射
@EnableConfigurationProperties(RedisProperties.class)
// 导入指定类
@Import({ LettuceConnectionConfiguration.class, JedisConnectionConfiguration.class })
public class RedisAutoConfiguration {

   // 配置Bean
   @Bean
   // 容器是否存在 redisTemplate Bean. 存在就不创建,不存在就进行创建。
   @ConditionalOnMissingBean(name = "redisTemplate")
   public RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory)
         throws UnknownHostException {
      RedisTemplate<Object, Object> template = new RedisTemplate<>();
      template.setConnectionFactory(redisConnectionFactory);
      return template;
   }

   // 同上面一样 
   @Bean
   @ConditionalOnMissingBean
   public StringRedisTemplate stringRedisTemplate(RedisConnectionFactory redisConnectionFactory)
         throws UnknownHostException {
      StringRedisTemplate template = new StringRedisTemplate();
      template.setConnectionFactory(redisConnectionFactory);
      return template;
   }

}

RedisProperties 配置类

@ConfigurationProperties(prefix = "spring.redis")
public class RedisProperties { 
    ... 
}

按照指定的前缀,在配置文件所配置的属性值都会映射到 RedisProperties 配置类里

基本上就是通过 AutoConfigurationImportSelector 为我们容器中注册组件,然后根据maven依赖导入的jar包,根据条件注解装配来指定哪些组件起作用,哪些组件不起作用。

springBoot的条件注解

条件注解:@ConditionalOnBean
处理的类:OnBeanCondition
处理逻辑:Spring容器中是否存在对应的实例。可以通过实例的类型、类名、注解、昵称去容器中查找(可以配置从当前容器中查找或者父容器中查找或者两者一起查找)这些属性都是数组,通过"与"的关系进行查找
举例说明:@ConditionalOnBean(javax.sql.DataSource.class); Spring容器或者所有父容器中需要存在至少一个javax.sql.DataSource类的实例

条件注解:@ConditionalOnClass
处理的类:OnClassCondition
处理逻辑:类加载器中是否存在对应的类。可以通过Class指定(value属性)或者Class的全名指定(name属性)。如果是多个类或者多个类名的话,关系是"与"关系,也就是说这些类或者类名都必须同时在类加载器中存在
举例说明:@ConditionalOnClass({ Configuration.class,FreeMarkerConfigurationFactory.class }) 类加载器中必须存在Configuration和FreeMarkerConfigurationFactory这两个类

条件注解:@ConditionalOnExpression
处理的类:OnExpressionCondition
处理逻辑:判断SpEL 表达式是否成立
举例说明:@ConditionalOnExpression("'${server.host}'=='localhost'") server.host配置项的值需要是localhost

条件注解:@ConditionalOnJava
处理的类:OnJavaCondition
处理逻辑:指定Java版本是否符合要求。内部有2个属性value和range。value表示一个枚举的Java版本,range表示比这个老或者新于等于指定的Java版本(默认是新于等于)。内部会基于某些jdk版本特有的类去类加载器中查询&#x
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值