1. 程式人生 > >Springboot---------執行原理

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   

    @SpringBootConfiguration繼承自@Configuration,二者功能也一致,標註當前類是配置類,並會將當前類內宣告的一個或多個以@Bean註解標記的方法的例項納入到spring容器中,並且例項名就是方法名。

    @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包在其他專案中引用。