1. 程式人生 > >Spring-Boot 載入Bean的幾種方式

Spring-Boot 載入Bean的幾種方式

Spring從3.0之後,就逐步傾向於使用java code config方式來進行bean的配置,在spring-boot中,這種風格就更為明顯了。
在檢視spring-boot工程的時候,總想著探究一下spring-boot如何簡單的宣告一個starter、Enable××,就能額外增加一個強大的功能,spring是如何找到這些具體的實現bean的呢。
目前,我總結大概有這麼幾種:

  1. 直接在工程中使用@Configuration註解
    這個就是基本的java code方式,在@SpringBootApplication裡面就包含了@ComponentScan,因而會把工程中的@Configuration註解找到,並加以解釋。
  2. 通過@Enable××註解裡面的@Import註解
    我們在Enable某個功能時,實際上是通過@Import註解載入了另外的配置屬性類。
    例如: 如果要給工程加上定時任務的功能,只需要在某個配置檔案上加上@EnableScheduling,實際上它是引入了SchedulingConfiguration.class,程式碼如下:
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Import(SchedulingConfiguration.class)
@Documented
public @interface EnableScheduling {
}

而SchedulingConfiguration就是一個標準的配置檔案了,裡面定義了ScheduledAnnotationBeanPostProcessor這個bean。

@Configuration
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
public class SchedulingConfiguration {
    @Bean(name = TaskManagementConfigUtils.SCHEDULED_ANNOTATION_PROCESSOR_BEAN_NAME)
    @Role(BeanDefinition.ROLE_INFRASTRUCTURE)
    public
ScheduledAnnotationBeanPostProcessor scheduledAnnotationProcessor()
{ return new ScheduledAnnotationBeanPostProcessor(); } }

有了ScheduledAnnotationBeanPostProcessor這bean,就會在context初始化時候,查詢我們程式碼中的@Scheduled,並把它們轉換為定時任務。

  1. 通過@EnableAutoConfiguration註解
    添加了這個異常強大的註解,spring-boot會利用AutoConfigurationImportSelector搜尋所有jar包中META-INF資料夾中spring.factories,找到其中org.springframework.boot.autoconfigure.EnableAutoConfiguration的屬性值,並把它作為需要解析的@Configuration檔案。
    例如:spring-cloud-commons裡面的spring.factories
# AutoConfiguration
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
org.springframework.cloud.client.CommonsClientAutoConfiguration,\
org.springframework.cloud.client.discovery.noop.NoopDiscoveryClientAutoConfiguration,\
org.springframework.cloud.client.hypermedia.CloudHypermediaAutoConfiguration,\
org.springframework.cloud.client.loadbalancer.AsyncLoadBalancerAutoConfiguration,\
org.springframework.cloud.client.loadbalancer.LoadBalancerAutoConfiguration,\
org.springframework.cloud.client.serviceregistry.ServiceRegistryAutoConfiguration,\
org.springframework.cloud.commons.util.UtilAutoConfiguration,\
org.springframework.cloud.client.discovery.simple.SimpleDiscoveryClientAutoConfiguration
  1. 自己實現ImportSelector
    AutoConfigurationImportSelector顯然有時候還是不夠用的,這時候就可以自己實現ImportSelector,實現更靈活的載入功能。
public interface ImportSelector {
    String[] selectImports(AnnotationMetadata importingClassMetadata);
}

ImportSelector介面定義了一個selectImports()方法,根據程式裡面定義的註解資訊,動態返回能被載入的類列表。這個實現就非常靈活了,簡單的可以自己判斷註解,直接返回類名;複雜的可以自己定製類似AutoConfigurationImportSelector的功能。
例如:我們看看spring-cloud的@EnableCircuitBreaker

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@Import(EnableCircuitBreakerImportSelector.class)
public @interface EnableCircuitBreaker {