title: Sring Boot 自動裝配 date: 2019-07-18 categories:java
SpringBoot和新特性筆記。spring
@sevice
@Conrtroller
@Repository
@Component
springboot
這幾個註解在Srping源碼
的文章中已經將結果了,這裏就不在贅述了。ide
Condition
註解做爲條件,若是符合條件則將bean
注入到IOC
中,反之則不注入,實際是使用 @Conditional
註解來實現,繼承 Condition
接口,經過 matches
方法進行邏輯判斷是否符合條件。測試
1: 建立ConditionOnSysProperty註解ui
/** * @Auther: lantao * @Date: 2019-07-18 17:52 * @Company: 隨行付支付有限公司 * @maill: lan_tao@suixingpay.com * @Description: TODO */
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE, ElementType.METHOD})
@Documented
@Conditional({SysPropertyCondition.class})
public @interface ConditionOnSysProperty {
String value() default "lantao";
}
複製代碼
2:建立@Condtional所須要的條件 SysPropertyConditionspa
/** * @Auther: lantao * @Date: 2019-07-18 17:52 * @Company: 隨行付支付有限公司 * @maill: lan_tao@suixingpay.com * @Description: TODO */
public class SysPropertyCondition implements Condition {
/** * 匹配方法 * * @param context * @param metadata * @return */
@Override
public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
// 獲取 ConditionOnSysProperty 註解的屬性
Map<String, Object> attributes = metadata.getAnnotationAttributes(ConditionOnSysProperty.class.getName());
String value = String.valueOf(attributes.get("value"));
// 獲取本機的user.name值
String propertieValue = System.getProperties().get("user.name").toString();
// 對比
return value.equals(propertieValue);
}
}
複製代碼
3:建立COnditionBootStrap測試code
/** * @Auther: lantao * @Date: 2019-07-18 17:44 * @Company: 隨行付支付有限公司 * @maill: lan_tao@suixingpay.com * @Description: TODO */
public class ConditionBootStrap {
@Bean
// 這了由於value是lantao, 正好user.name也是lantao,因此條件成立,會將bean注入到ioc中
@ConditionOnSysProperty(value = "lantao")
private String helloWorld() {
return "Hello World ! Condition";
}
public static void main(String[] args) {
// 這種方式能夠不使用 SpringBootApplication 註解
ConfigurableApplicationContext context = new SpringApplicationBuilder(ConditionBootStrap.class).run(args);
// 獲取名爲 helloWorld 的Bean,判斷 ConditionOnSysProperty 條件是否生效
String helloWorld = context.getBean("helloWorld", String.class);
System.out.println(helloWorld);
// 關閉
context.close();
}
}
結果:
Hello World ! Condition
複製代碼
Eanble
註解內部使用@Import
將 bean
注入到ioc
中,@import
註解中能夠直接放入bean
,也能夠作更靈活的配置,使用繼承了ImportSeletor
接口的bean,能夠根據@Enable
註解的屬性(attrbutes)
進行靈活的動態判斷cdn
1: 建立 EnableHelloWorld繼承
/** * @Auther: lantao * @Date: 2019-07-18 18:03 * @Company: 隨行付支付有限公司 * @maill: lan_tao@suixingpay.com * @Description: TODO */
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
// 直接使用沒法靈活判斷
//@Import(TestConfiguration.class)
// 使用 HelloWorldImportSeletor 能夠有更靈活的判斷
@Import(HelloWorldImportSeletor.class)
public @interface EnableHelloWorld {
String name() default "lantao";
}
複製代碼
2: 建立TestConfiguration和Test1Configuration
public class TestConfiguration {
@Bean
private String helloWorld() {
return "hello World! Enable";
}
}
public class Test1Configuration {
@Bean
public String buzhidao() {
return "不知道";
}
}
複製代碼
3: 建立HelloWorldImportSeletor
/** * @Auther: lantao * @Date: 2019-07-19 09:55 * @Company: 隨行付支付有限公司 * @maill: lan_tao@suixingpay.com * @Description: TODO */
public class HelloWorldImportSeletor implements ImportSelector {
@Override
public String[] selectImports(AnnotationMetadata importingClassMetadata) {
// 獲取EnableHelloWorld註解的屬性
Map<String, Object> attributes = importingClassMetadata.getAnnotationAttributes(EnableHelloWorld.class.getName());
// 根據attributes 靈活判斷注入那個bean
if ("lantao".equals(attributes.get("name"))) {
System.out.println(TestConfiguration.class.getName());
return new String[]{TestConfiguration.class.getName()};
}
System.out.println(TestConfiguration.class.getName());
return new String[]{Test1Configuration.class.getName()};
}
}
複製代碼
4:建立bootStrap測試
/** * @Auther: lantao * @Date: 2019-07-18 18:04 * @Company: 隨行付支付有限公司 * @maill: lan_tao@suixingpay.com * @Description: TODO */
@EnableHelloWorld
//@EnableHelloWorld(name = "buzhidao")
public class EnableBootStrap {
public static void main(String[] args) {
// 這種方式能夠不使用 SpringBootApplication 註解
ConfigurableApplicationContext context = new SpringApplicationBuilder(EnableBootStrap.class).run(args);
// 獲取名爲 helloWorld 的Bean,判斷 ConditionOnSysProperty 條件是否生效
String helloWorld = context.getBean("helloWorld", String.class);
// 這裏能夠獲取 bean名稱爲 'buzhidao',須要註解@EnableHelloWorld(name = "buzhidao"),
// 由於@EnableHelloWorld的name默認值是lantao,符合Condition的條件判斷
// String helloWorld = context.getBean("buzhidao", String.class);
System.out.println(helloWorld);
// 關閉
context.close();
}
}
結果:
hello World! Enable
複製代碼
自定義spring.factories,工廠模式裝配能夠自定義starter。
1: 建立SpringFactoriesConfiguration
/** * @Auther: lantao * @Date: 2019-07-22 10:10 * @Company: 隨行付支付有限公司 * @maill: lan_tao@suixingpay.com * @Description: TODO */
@EnableHelloWorld
@ConditionOnSysProperty(value = "lantao")
@Configuration
public class SpringFactoriesConfiguration {
// 這裏沒有寫 bean 的注入,直接引用 Condition 和 eanble 模塊註解。
// eanble註解內部使用import將bean注入到ioc中,@import註解中能夠直接放入bean,也能夠作更靈活的配置使用繼承了ImportSeletor接口的bean,
// 能夠根據enable註解的屬性(attrbutes)進行靈活的動態判斷
// Condition 註解做爲條件,若是符合條件則將bean注入到IOC中,反之則不注入,實際是使用 @Conditional註解來實現,經過繼承 Condition 接口,
// 經過 matches 方法進行邏輯判斷是否符合條件。
}
複製代碼
2: 建立 META-INF/spring.factories
# Auto Configure
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.lantao.springboot_leran.spring_factories_leran.config.SpringFactoriesConfiguration
複製代碼
3: 建立 SpringFactoriesBootStrap 引導類
/** * @Auther: lantao * @Date: 2019-07-19 16:01 * @Company: 隨行付支付有限公司 * @maill: lan_tao@suixingpay.com * @Description: TODO */
@EnableAutoConfiguration
public class SpringFactoriesBootStrap {
public static void main(String[] args) {
ConfigurableApplicationContext context = new SpringApplicationBuilder(SpringFactoriesBootStrap.class).run(args);
String helloWorld = context.getBean("helloWorld", String.class);
System.out.println(helloWorld);
context.close();
}
}
結果:
hello World! Enable
複製代碼