1 @SpringBootApplication 2 public class DemoApplication { 3 public static void main(String[] args) { 4 5 SpringApplication.run(DemoApplication.class, args); 6 } 7 }
每次咱們直接直接啓動這個啓動類,SpringBoot就啓動成功了,而且幫咱們配置了好多自動配置類。redis
其中最重要是 @SpringBootApplication 這個註解,咱們點進去看一下。spring
1 @Target(ElementType.TYPE) 2 @Retention(RetentionPolicy.RUNTIME) 3 @Documented 4 @Inherited 5 @SpringBootConfiguration 6 @EnableAutoConfiguration 7 @ComponentScan(excludeFilters = { 8 @Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class), 9 @Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) }) 10 public @interface SpringBootApplication {
@SpringBootConfiguration : Spring Boot的配置類,標註在某個類上,表示這是一個Spring Boot的配置類app
@EnableAutoConfiguration: 開啓自動配置類,SpringBoot的精華所在。框架
@ComponentScan包掃描ide
之前咱們須要配置的東西,Spring Boot幫咱們自動配置;@EnableAutoConfiguration告訴SpringBoot開啓自動配置功能;這樣自動配置才能生效;工具
1 @Target(ElementType.TYPE) 2 @Retention(RetentionPolicy.RUNTIME) 3 @Documented 4 @Inherited 5 @AutoConfigurationPackage 6 @Import(AutoConfigurationImportSelector.class) 7 public @interface EnableAutoConfiguration {
@AutoConfigurationPackage:自動配置包學習
@Import: 導入自動配置的組件this
1 static class Registrar implements ImportBeanDefinitionRegistrar, DeterminableImports { 2 3 @Override 4 public void registerBeanDefinitions(AnnotationMetadata metadata, 5 BeanDefinitionRegistry registry) { 6 register(registry, new PackageImport(metadata).getPackageName()); 7 }
它實際上是註冊了一個Bean的定義。spa
new PackageImport(metadata).getPackageName(),它其實返回了當前主程序類的 同級以及子級 的包組件。3d
以上圖爲例,DemoApplication是和demo包同級,可是demo2這個類是DemoApplication的父級,和example包同級
也就是說,DemoApplication啓動加載的Bean中,並不會加載demo2,這也就是爲何,咱們要把DemoApplication放在項目的最高級中。
能夠從圖中看出 AutoConfigurationImportSelector 繼承了 DeferredImportSelector 繼承了 ImportSelector
ImportSelector有一個方法爲:selectImports。
1 @Override 2 public String[] selectImports(AnnotationMetadata annotationMetadata) { 3 if (!isEnabled(annotationMetadata)) { 4 return NO_IMPORTS; 5 } 6 AutoConfigurationMetadata autoConfigurationMetadata = AutoConfigurationMetadataLoader 7 .loadMetadata(this.beanClassLoader); 8 AnnotationAttributes attributes = getAttributes(annotationMetadata); 9 List<String> configurations = getCandidateConfigurations(annotationMetadata, 10 attributes); 11 configurations = removeDuplicates(configurations); 12 Set<String> exclusions = getExclusions(annotationMetadata, attributes); 13 checkExcludedClasses(configurations, exclusions); 14 configurations.removeAll(exclusions); 15 configurations = filter(configurations, autoConfigurationMetadata); 16 fireAutoConfigurationImportEvents(configurations, exclusions); 17 return StringUtils.toStringArray(configurations); 18 }
能夠看到第九行,它實際上是去加載 public static final String FACTORIES_RESOURCE_LOCATION = "META-INF/spring.factories";外部文件。這個外部文件,有不少自動配置的類。以下:
咱們以RedisTemplate爲例:
1 @Configuration 2 @ConditionalOnClass(RedisOperations.class) 3 @EnableConfigurationProperties(RedisProperties.class) 4 @Import({ LettuceConnectionConfiguration.class, JedisConnectionConfiguration.class }) 5 public class RedisAutoConfiguration { 6 7 @Bean 8 @ConditionalOnMissingBean(name = "redisTemplate") 9 public RedisTemplate<Object, Object> redisTemplate( 10 RedisConnectionFactory redisConnectionFactory) throws UnknownHostException { 11 RedisTemplate<Object, Object> template = new RedisTemplate<>(); 12 template.setConnectionFactory(redisConnectionFactory); 13 return template; 14 } 15 16 @Bean 17 @ConditionalOnMissingBean 18 public StringRedisTemplate stringRedisTemplate( 19 RedisConnectionFactory redisConnectionFactory) throws UnknownHostException { 20 StringRedisTemplate template = new StringRedisTemplate(); 21 template.setConnectionFactory(redisConnectionFactory); 22 return template; 23 } 24 25 }
咱們每次在Spring中使用Redis,都會使用到RedisTemplate這個工具類,可是他默認給咱們返回的這個工具類,可能不是很符合咱們的要求。好比:咱們想要開啓事務,或者想要改變它默認的序列化。
這時候該如何去作呢?
根據前面的分析,只要咱們在容器中放入一個RedisTemplate Bean便可。
1 @Bean("redisTemplate") 2 public RedisTemplate<Object, Object> myRedisTemplate( 3 RedisConnectionFactory redisConnectionFactory) { 4 RedisTemplate<Object, Object> template = new RedisTemplate<>(); 5 template.setConnectionFactory(redisConnectionFactory); 6 // 修改序列化爲Jackson 7 template.setDefaultSerializer(new GenericJackson2JsonRedisSerializer()); 8 // 開啓事務 9 template.setEnableTransactionSupport(true); 10 return template; 11 }
咱們本身定義咱們的RedisTemplate模板,修改序列化,開啓事務等操做。
咱們將咱們本身的Bean加入到IoC容器中之後,他就會默認的覆蓋掉原來的RedisTemplate,達到定製的效果。
咱們在以Kafka爲例:
假設咱們想要消費的對象不是字符串,而是一個對象呢?好比Person對象,或者其餘Object類呢?
1:咱們首先去查找KafkaAutoConfiguration(xxxAutoConfiguration),看看是否有關於Serializer屬性的配置
2:假設沒有咱們就去KafkaProperties文件查找是否有Serializer的配置
而後直接在application.properties修改默認序列化就好,連Bean都不須要本身重寫。
相似這種,可使用Spring提供的Json序列化,也能夠自動使用第三方框架提供的序列化,好比Avro, Protobuff等
1 spring.kafka.producer.key-serializer=org.springframework.kafka.support.serializer.JsonSerializer 2 spring.kafka.producer.value-serializer=org.springframework.kafka.support.serializer.JsonSerializer 3 spring.kafka.consumer.key-deserializer=com.example.common.MyJson 4 spring.kafka.consumer.value-deserializer=com.example.common.MyJson
後記: