Springboot---------執行原理
@SpringBootApplication註解詳解
@SpringBootApplication註解作為Springboot的啟動入口,我們會在main函式上新增@SpringBootApplication註解。該註解時一個組合註解,註解的定義如下:
@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 { }
@Documented
Documented 註解表明這個註解應該被 javadoc工具記錄. 預設情況下,javadoc是不包括註解的. 但如果宣告註解時指定了 @Documented,則它會被 javadoc 之類的工具處理, 所以註解型別資訊也會被包括在生成的文件中。
@Inherited
@Inherited:允許子類繼承父類的註解。例項如下
@Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) @Inherited public @interface DBTable { public String name() default ""; } @Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) public @interface DBTable2 { public String name() default ""; } @DBTable class Super{ private int superPrivateF; public int superPublicF; public Super(){ } private int superPrivateM(){ return 0; } public int superPubliceM(){ return 0; } } @DBTable2 class Sub extends Super{ private int subPrivateF; public int subPublicF; private Sub(){ } public Sub(int i){ } private int subPrivateM(){ return 0; } public int subPubliceM(){ return 0; } }
@SpringBootConfiguration
@Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) @Documented @Configuration public @interface SpringBootConfiguration { }
@SpringBootConfiguration的例項如下
package com.lhkj.pluto.config; import java.util.HashMap; import java.util.Map; import org.springframework.boot.SpringBootConfiguration; import org.springframework.context.annotation.Bean; @SpringBootConfiguration public class Config { @Bean public Map createMap(){ Map map = new HashMap(); map.put("username","gxz"); map.put("age",27); return map; } }
@EnableAutoConfiguration
@ComponentScan
核心註解
@ConditionalOnBean(僅僅在當前上下文中存在某個物件時,才會例項化一個Bean)
@ConditionalOnClass(某個class位於類路徑上,才會例項化一個Bean)
@ConditionalOnExpression(當表示式為true的時候,才會例項化一個Bean)
@ConditionalOnMissingBean(僅僅在當前上下文中不存在某個物件時,才會例項化一個Bean)
@ConditionalOnMissingClass(某個class類路徑上不存在的時候,才會例項化一個Bean)
@ConditionalOnResource(類路徑是否有指定的值)
@ConditionalOnProperty(指定的屬性有指定的值)
@ConditionalOnNotWebApplication(不是web應用)
@ConditionalOnBean例項如下
@Configuration public class ConditionalOnBeanConfig { @Bean public A beanA(){ return new A(); // 建立一個Bean,名稱是 beanA,不需要滿足什麼前置條件, } @Bean @ConditionalOnBean(name="beanA") public B beanB(){ // 僅在beanFactory存在一個名稱叫做beanA的bean時,當前方法初始化一個名字為beanB的bean。 return new B(); } @Bean @ConditionalOnBean public C beanC(){ //如果beanFactory不存在一個型別為C的bean,則不建立該bean。 // 如果當前專案僅有這一個 bean 配置檔案,則因為 beanFactory 中不存在一個型別為C的 bean ,所以當前 // 方法定義的名稱為 beanC 的 bean 並不會被初始化。 return new C(); } }
@ConditionalOnProperty例項
@ConditionalOnProperty註解判斷Cofiguration是否生效,
@Retention(RetentionPolicy.RUNTIME) @Target({ElementType.TYPE, ElementType.METHOD}) @Documented @Conditional({OnPropertyCondition.class}) public @interface ConditionalOnProperty { String[] value() default {}; //陣列,獲取對應property名稱的值,與name不可同時使用 String prefix() default "";//property名稱的字首,可有可無 String[] name() default {};//陣列,property完整名稱或部分名稱(可與prefix組合使用,組成完整的property名稱),與value不可同時使用 String havingValue() default "";//可與name組合使用,比較獲取到的屬性值與havingValue給定的值是否相同,相同才載入配置 boolean matchIfMissing() default false;//缺少該property時是否可以載入。如果為true,沒有該property也會正常載入;反之報錯 boolean relaxedNames() default true;//是否可以鬆散匹配,至今不知道怎麼使用的 }
例項
@Configuration //在application.properties配置"mf.assert",對應的值為true @ConditionalOnProperty(prefix="mf",name = "assert", havingValue = "true") public class AssertConfig { @Autowired private HelloServiceProperties helloServiceProperties; @Bean public HelloService helloService(){ HelloService helloService = new HelloService(); helloService.setMsg(helloServiceProperties.getMsg()); return helloService; } }
實戰分析
屬性配置
package com.kingdee.domains; import org.springframework.boot.context.properties.ConfigurationProperties; @ConfigurationProperties public class HelloServiceProperties { private static final String MSG = "world"; private String msg = MSG; public String getMsg() { return msg; } public void setMsg(String msg) { this.msg = msg; } }
判斷依據類
package com.kingdee.service; public class HelloService { private String msg; public String getMsg() { return msg; } public void setMsg(String msg) { this.msg = msg; } }
自動配置類
package com.kingdee; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import com.kingdee.domains.HelloServiceProperties; import com.kingdee.service.HelloService; @Configuration @EnableConfigurationProperties @ConditionalOnClass(HelloService.class) @ConditionalOnProperty(prefix="hello",value="enables",matchIfMissing=true) public class HelloServiceAutoConfiguration { @Autowired private HelloServiceProperties helloServiceProperties; @Bean @ConditionalOnMissingBean() public HelloService helloService(){ HelloService helloService = new HelloService(); helloService.setMsg(helloServiceProperties.getMsg()); return helloService; } }
@EnableConfigurationProperties在SpringBoot的註釋中是這樣說明的:為帶有@ConfigurationProperties註解的Bean提供有效的支援。這個註解可以提供一種方便的方式來將帶 @ConfigurationProperties註解的類注入為Spring容器的Bean。將配置檔案中對應的值和指定類繫結起來;並把HttpEncodingProperties加入到ioc容器中。
建立spring.factories
在resources下面建立META-INF/spring.factories, 然後在檔案中把第三步的類配置進去,如下:
org.springframework.boot.autoconfigure.EnableAutoConfiguration=com.kingdee.HelloServiceAutoConfiguration
封裝成包
分裝成jar包後,就可以將該jar包在其他專案中引用。