1. 程式人生 > >一步步從Spring Framework裝配掌握SpringBoot自動裝配

一步步從Spring Framework裝配掌握SpringBoot自動裝配

目錄

Spring Framework模式註解

模式註解是一種用於宣告在應用中扮演“元件”角色的註解。如 Spring Framework 中的 @Repository 標註在任何類上 ,用
於扮演倉儲角色的模式註解。

模式註解(角色註解)

Spring Framework 註解 場景說明
@Component 通用元件模式註解
@Controller Web 控制器模式註解
@Service 服務模式註解
@Repository 資料倉儲模式註解
@Configuration 配置類模式註解

在Spring中進行裝配

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-
context.xsd">
<!-- 啟用註解驅動特性 -->
<context:annotation-config />
<!-- 找尋被 @Component 或者其派生 Annotation 標記的類(Class),將它們註冊為 Spring Bean -->
<context:component-scan base-package="com.imooc.dive.in.spring.boot" />
</beans>

在Spring中基於Java註解配置方式

@ComponentScan(basePackages = "com.imooc.dive.in.spring.boot")
public class SpringConfiguration {
...
}

實戰:自定義模式註解

@Component 模式註解具有“派生性”和“層次性”,我們能夠自定義建立Bean註解

第一步:自定義SpringBean註解

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Component
public @interface MyServiceAnnotation {
    String value() default "";
}

第二步:將註解作用在自定義Bean上

@MyServiceAnnotation(value = "testBean")
public class TestBean {
    
}

第三步:測試是否可以從Spring容器中獲取到自定義Bean

@SpringBootApplication
public class Main {
    public static void main(String[] args) {
        ConfigurableApplicationContext run = SpringApplication.run(Main.class, args);
        TestBean testBean = run.getBean("testBean", TestBean.class);
        System.out.println("testBean" + testBean.toString());
        run.close();
    }
}

Spring [email protected]模組裝配

Spring Framework 3.1 開始支援”@Enable 模組驅動“。所謂“模組”是指具備相同領域的功能元件集合, 組合所形成一個獨立的單元。比如 Web MVC 模組、AspectJ代理模組、Caching(快取)模組、JMX(Java 管 理擴充套件)模組、Async(非同步處理)模組等。

@Enable 註解模組舉例

框架實現 @Enable 註解模組 啟用模組
Spring Framework @EnableWebMvc Web MVC 模組
Spring Framework @EnableTransactionManagement 事務管理模組
Spring Framework @EnableCaching Caching 模組
Spring Framework @EnableMBeanExport JMX 模組
Spring Framework @EnableAsync 非同步處理模組
Spring Framework @EnableWebFlux Web Flux 模組
Spring Framework @EnableAspectJAutoProxy AspectJ 代理模組
Spring Boot @EnableAutoConfiguration 自動裝配模組
Spring Boot @EnableManagementContext Actuator 管理模組
Spring Boot @EnableConfigurationProperties 配置屬性繫結模組
Spring Boot @EnableOAuth2Sso OAuth2 單點登入模組
......

@Enable實現方式

  • 註解驅動方式
  • 介面程式設計方式

實戰:自定義@Enable註解驅動實現方式

第一步:實現自定義註解@EnableMyBean

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import(MyBeanConfig.class)
public @interface EnableMyBean {
}

PS:注意@Import(MyBeanConfig.class),將匯入MyBeanConfig配置類的相關Bean

第二步:建立MyBeanConfig配置類

@Configuration
public class MyBeanConfig {
    @Bean(name = "hello")
    public String hello() {
        return "word";
    }
}

第三步:在應用中測試使用@EnableMyBean

@SpringBootApplication(scanBasePackages = "com.jimisun.learnspringboot.three")
@EnableMyBean
public class Main {
    public static void main(String[] args) {
        ConfigurableApplicationContext context =
                new SpringApplicationBuilder(Main.class)
                        .web(WebApplicationType.NONE)
                        .run(args);
        String bean = context.getBean("hello", String.class);
        context.close();

    }
}

實戰:自定義@Enable介面實現方式

第一步:實現自定義註解@EnableMyBean

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import(MyBeanConfigSelector.class)
public @interface EnableMyBean {
}

PS:注意@Import(MyBeanConfigSelector.class)匯入的類和@Enable註解驅動匯入的不一樣,這裡匯入的是一個實現了ImportSelector介面的類

public class MyBeanConfigSelector implements ImportSelector {


    @Override
    public String[] selectImports(AnnotationMetadata annotationMetadata) {
        return new String[]{new MyBeanConfig().getClass().getName()};
    }
}

PS:在MyBeanConfigSelector類中我們可以自定義複雜的邏輯,這裡我們僅僅簡單返回MyBeanConfig配置類。

第三步:建立MyBeanConfig配置類

@Configuration
public class MyBeanConfig {
    @Bean
    public String hello() {
        return "word";
    }
}

第四步:在應用中測試使用@EnableMyBean

@SpringBootApplication(scanBasePackages = "com.jimisun.learnspringboot.four")
@EnableMyBean
public class Main {
    public static void main(String[] args) {
        ConfigurableApplicationContext context =
                new SpringApplicationBuilder(Main.class)
                        .web(WebApplicationType.NONE)
                        .run(args);
        String bean = context.getBean("hello", String.class);
        context.close();

    }
}

PS:其實@Enable介面的實現方式和@Enable註解實現方式是基本一樣的,只不過多了一個步驟,方便我們更靈活地進行編寫邏輯。

Spring Framework條件裝配

從 Spring Framework 3.1 開始,允許在 Bean 裝配時增加前置條件判斷

Spring 註解 場景說明 起始版本
@Profile 配置化條件裝配 3.1
@Conditional 程式設計條件裝配 4.0

實戰:自定義@Profile 配置化條件裝配

第一步:自定義建立某服務不同的@Profile實現類

public interface UserService {
    void println();
}
@Service
@Profile("vip")
public class VipUserservice implements UserService {
    @Override
    public void println() {
        System.out.println("I am VIP User");
    }
}
@Service
@Profile("common")
public class CommonUserservice implements UserService {
    @Override
    public void println() {
        System.out.println("I am Common User");
    }
}

第二步:在構建Spring容器指定配置

@ComponentScan(basePackages = "com.jimisun.learnspringboot.two")
public class Main {

    public static void main(String[] args) {
        ConfigurableApplicationContext run = new SpringApplicationBuilder(Main.class).
                web(WebApplicationType.NONE).
                profiles("vip").
                run(args);
        UserService bean = run.getBean(UserService.class);
        bean.println();
        run.close();
    }
}

實戰:自定義@Conditional 程式設計條件裝配

第一步:建立一個自定義註解

@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE, ElementType.METHOD})
@Documented
@Conditional({MyOnConditionProperty.class})
public @interface MyConditionOnPropertyAnnotion {
    String prefix() default "";
}

PS:注意@Conditional註解,將會找到MyOnConditionProperty類的matches方法進行條件驗證

第二步:建立該註解的條件驗證類,該類實現Condition介面

public class MyOnConditionProperty implements Condition {

    @Override
    public boolean matches(ConditionContext conditionContext, AnnotatedTypeMetadata annotatedTypeMetadata) {
        Map<String, Object> annotationAttributes =
                annotatedTypeMetadata.getAnnotationAttributes(MyConditionOnPropertyAnnotion.class.getName());
        String prefix = String.valueOf(annotationAttributes.get("prefix"));
        return prefix.equals("pass");
    }
}

第三步:在Spring應用中應用條件裝配

@SpringBootApplication
public class Main {


    @Bean(name = "hello")
    @MyConditionOnPropertyAnnotion(prefix = "pass")
    public String hello() {
        return "word";
    }

    public static void main(String[] args) {
        ConfigurableApplicationContext context =
                new SpringApplicationBuilder(Main.class)
                        .web(WebApplicationType.NONE)
                        .run(args);
        String bean = context.getBean("hello", String.class);
        context.close();


    }
}

PS:本例自定義的MyConditionOnPropertyAnnotion在應用中裝配的時候可以指定prefix值,該值將會在實現了Condition藉口的matches進行條件驗證,如果驗證通過,則在Spring容器中裝配該Bean,反之則不裝配。

SpringBoot 自動裝配

在 Spring Boot 場景下,基於約定大於配置的原則,實現 Spring 元件自動裝配的目的。其中底層使用了一系列的Spring Framework手動裝配的方法來構成Spring Boot自動裝配。

自定義SpringBoot自動裝配

  1. 啟用自動裝配 - @EnableAutoConfiguration
  2. 實現自動裝配 - XXXAutoConfiguration
  3. 配置自動裝配實現 - META-INF/spring.factories

第一步 :啟用自動裝配 - @EnableAutoConfiguration

@EnableAutoConfiguration
public class Main {
    public static void main(String[] args) {
        ConfigurableApplicationContext context =
                new SpringApplicationBuilder(Main.class)
                        .web(WebApplicationType.NONE)
                        .run(args);
        String bean = context.getBean("hello", String.class);
        context.close();

    }
}

第二步:實現自動裝配 - XXXAutoConfiguration

@Configuration
@EnableMyBean
public class HelloWordAutoConfiguration {
}

PS:這裡使用了上面我們建立的@EnableMyBean,這個註解會注入一個名為“hello"的Bean

第三步:配置自動裝配實現 - META-INF/spring.factories

在ClassPath目錄下建立META-INF資料夾再建立spring.factories檔案

#配置自己的自動裝配Bean
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.jimisun.learnspringboot.five.HelloWordAutoConfiguration

最後:執行測試第一步中的Main方法,看是否能獲取到名為“hello”的Bean

本章總結

本章我們主要了解了Spring Framework的模式註解裝配,@Enable裝配和條件裝配。對於SpringBoot的自動裝配我們僅僅做了一下演示,遵循SpringBoot裝配的三個步驟,我們就可以執行SpringBoot的自動裝配。但是對於SpringBoot為什麼要遵循這三個步驟?自動裝配的原理?我們不知所以然,所以下一章節我們仍然以SpringBoot的自動裝配為主題,對SpringBoot的底層原始碼做剖析。