006-Spring Boot自動配置
一、接口Condition、Conditional(原理)
主要提供一下方法
boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata);
true:表示裝配
false:表示不裝配
註解:Conditional() 參數是數組,數組內的都是true才裝配
@Target({ElementType.TYPE, ElementType.METHOD}) @Retention(RetentionPolicy.RUNTIME) @Documented public @interfaceView CodeConditional { /** * All {@link Condition}s that must {@linkplain Condition#matches match} * in order for the component to be registered. */ Class<? extends Condition>[] value(); }
通常配合使用。
示例:
接口:EncodingConvert
package com.lhx.spring.springboot_auto_config;View Codepublic interface EncodingConvert { }
接口實現一:UTF8EncodingConvert
package com.lhx.spring.springboot_auto_config; public class UTF8EncodingConvert implements EncodingConvert { }View Code
接口實現二:GBKEncodingConvert
package com.lhx.spring.springboot_auto_config; publicView Codeclass GBKEncodingConvert implements EncodingConvert { }
配置類:
package com.lhx.spring.springboot_auto_config; import org.springframework.boot.SpringBootConfiguration; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Conditional; @SpringBootConfiguration public class EncodingConvertConfiguration { @Bean public EncodingConvert createGBKEncodingConvert() { return new GBKEncodingConvert(); } @Bean public EncodingConvert createUTF8EncodingConvert() { return new UTF8EncodingConvert(); } }View Code
App:
package com.lhx.spring.springboot_auto_config; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.context.ConfigurableApplicationContext; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Condition; import org.springframework.context.annotation.Conditional; @SpringBootApplication public class App { @Bean public Runnable createRunnable() { return () -> { System.out.println("spring boot is running"); }; } public static void main(String[] args) { ConfigurableApplicationContext context = SpringApplication.run(App.class, args); context.getBean(Runnable.class).run(); //可以通過啟動參數修改-Dfile.encoding=GBK System.out.println(System.getProperty("file.encoding")); System.out.println(context.getBeansOfType(EncodingConvert.class)); context.close(); } }View Code
此時,會發現連個接口實現都會被裝配進來。
UTF8Condition實現Condition接口
package com.lhx.spring.springboot_auto_config; import org.springframework.context.annotation.Condition; import org.springframework.context.annotation.ConditionContext; import org.springframework.core.type.AnnotatedTypeMetadata; public class UTF8Condition implements Condition { @Override public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) { String encoding = System.getProperty("file.encoding"); if (encoding != null) { return "utf-8".equalsIgnoreCase(encoding); } return false; } }View Code
GBKCondition實現Condition接口
package com.lhx.spring.springboot_auto_config; import org.springframework.context.annotation.Condition; import org.springframework.context.annotation.ConditionContext; import org.springframework.core.type.AnnotatedTypeMetadata; public class GBKCondition implements Condition { @Override public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) { String encoding = System.getProperty("file.encoding"); if (encoding != null) { return "gbk".equalsIgnoreCase(encoding); } return false; } }View Code
修改配置類
package com.lhx.spring.springboot_auto_config; import org.springframework.boot.SpringBootConfiguration; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Conditional; @SpringBootConfiguration public class EncodingConvertConfiguration { @Bean @Conditional(GBKCondition.class) public EncodingConvert createGBKEncodingConvert() { return new GBKEncodingConvert(); } @Bean @Conditional(UTF8Condition.class) public EncodingConvert createUTF8EncodingConvert() { return new UTF8EncodingConvert(); } }View Code
此時,會發現會根據file.encoding值來裝配接口類。
可在啟動參數增加
-Dfile.encoding=GBK
然後調試,發現裝配類也變了
註意:@Conditional也可以作用在類上
二、Spring提供的Conditional自動配置
jar:spring-boot-autoconfigure中,org.springframework.boot.autoconfigure.condition;即spring-boot提供
ConditionalOnBean:當存在某個bean時候裝配
ConditionalOnMissingBean:當不存在某個bean時候裝配
ConditionalOnClass:當classpath有才裝配
ConditionalOnExpression:
ConditionalOnJava:JDK版本符合時候才裝配
ConditionalOnNotWebApplication:不是web環境才裝配
ConditionalOnWebApplication:是web環境才裝配
ConditionalOnResource:資源存在才裝配
ConditionalOnProperty:配置存在才裝配
示例一:ConditionalOnProperty 配置存在匹配時候才配置
增加配置類
package com.lhx.spring.springboot_auto_config; import org.springframework.boot.SpringBootConfiguration; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.context.annotation.Bean; @SpringBootConfiguration public class UserConfiguration { @Bean @ConditionalOnProperty(name = "runnable.enable", havingValue = "true") public Runnable createRunnable() { return () -> { }; } }View Code
App2編寫
package com.lhx.spring.springboot_auto_config; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.context.ConfigurableApplicationContext; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Condition; import org.springframework.context.annotation.Conditional; @SpringBootApplication public class App2 { public static void main(String[] args) { ConfigurableApplicationContext context = SpringApplication.run(App2.class, args); System.out.println(context.getBeansOfType(Runnable.class)); context.close(); } }View Code
默認是不能裝配的
可以再application.properties中添加runnable.enable=true即可裝配
或者@ConditionalOnProperty(name = "runnable.enable", havingValue = "true")增加
matchIfMissing=true,表示配置沒有的時候也生效
示例二:ConditionalOnClass classpath有某個類才裝配
增加或刪除maven,查看效果
<dependency> <groupId>com.google.code.gson</groupId> <artifactId>gson</artifactId> <version>2.8.2</version> </dependency>
使用代碼
@Bean @ConditionalOnClass(name="com.google.gson.Gson") public Runnable createGsonRunnable() { return () -> { }; }
示例三、ConditionalOnBean:根據容器中是否存在某個Bean進行裝配
@Bean @ConditionalOnBean(name="user") public Runnable createOnBeanRunnable() { return () -> { }; }
006-Spring Boot自動配置