一步步從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 Framework@Enable模塊裝配

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的底層源碼做剖析。

該教程所屬Java工程師之SpringBoot系列教程,本系列相關博文目錄 Java工程師之SpringBoot系列教程前言&目錄

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章