Springboot自動裝配整理

首先寫一個咱們本身的HelloWorld配置類spring

一、基於"註解驅動"實現@Enable模塊編程

@Configuration
public class HelloWorldConfiguration {
    @Bean
    public String helloWorld() {
        return "Hello,World";
    }
}

再模仿Spring Cloud Feign源碼解析 中的@EnableFeignClients代碼寫一個咱們本身的標籤數組

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

@EnableFeignClients Import的是FeignClientsRegistrar.class而咱們這裏導入的是HelloWorldConfiguration.class服務器

再編寫一個引導類來看一下效果。ide

@EnableHelloWorld
@Configuration
public class EnabledHelloWorldBootstrap {
    public static void main(String[] args) {
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
        context.register(EnabledHelloWorldBootstrap.class);
        context.refresh();
        String helloWorld = context.getBean("helloWorld", String.class);
        System.out.printf("helloWorld = %s \n",helloWorld);
        context.close();
    }
}

運行結果(部分)ui

15:00:46.060 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Returning cached instance of singleton bean 'lifecycleProcessor'
15:00:46.065 [main] DEBUG org.springframework.core.env.PropertySourcesPropertyResolver - Could not find key 'spring.liveBeansView.mbeanDomain' in any property source
15:00:46.069 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Returning cached instance of singleton bean 'helloWorld'
helloWorld = Hello,World
15:00:46.069 [main] INFO org.springframework.context.annotation.AnnotationConfigApplicationContext - Closing org.springframework.context.annotation.AnnotationConfigApplicationContext@31a5c39e: startup date [Thu Nov 21 15:00:45 CST 2019]; root of context hierarchy
15:00:46.070 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Returning cached instance of singleton bean 'lifecycleProcessor'
15:00:46.070 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Destroying singletons in org.springframework.beans.factory.support.DefaultListableBeanFactory@5427c60c: defining beans [org.springframework.context.annotation.internalConfigurationAnnotationProcessor,org.springframework.context.annotation.internalAutowiredAnnotationProcessor,org.springframework.context.annotation.internalRequiredAnnotationProcessor,org.springframework.context.annotation.internalCommonAnnotationProcessor,org.springframework.context.event.internalEventListenerProcessor,org.springframework.context.event.internalEventListenerFactory,enabledHelloWorldBootstrap,com.cloud.demo.config.HelloWorldConfiguration,helloWorld]; root of factory hierarchyspa

二、基於"接口編程"實現@Enable模塊.net

基於ImportSelector接口實現server

假設當前應用支持兩種服務類型:HTTP和FTP,經過@EnableServer設置服務器類型(type)提供對應的服務對象

先定義一個服務接口

public interface Server {
    /**
     * 啓動服務器
     */
    void start();

    /**
     * 關閉服務器
     */
    void stop();

    /**
     * 服務器類型
     */
    enum Type {
        HTTP, //HTTP服務器
        FTP   //FTP服務器
    }
}

兩個實現類

@Component
public class HTTPServer implements Server {
    @Override
    public void start() {
        System.out.println("HTTP服務器啓動中...");
    }

    @Override
    public void stop() {
        System.out.println("HTTP服務器關閉中...");
    }
}
@Component
public class FTPServer implements Server {
    @Override
    public void start() {
        System.out.println("FTP服務器啓動中...");
    }

    @Override
    public void stop() {
        System.out.println("FTP服務器關閉中...");
    }
}

實現@Enable模塊驅動

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import(ServerImportSelector.class)
public @interface EnableServer {
    /**
     * 設置服務器類型
     * @return
     */
    Server.Type type();
}

實現Server ImportSelector接口

public class ServerImportSelector implements ImportSelector {
    @Override
    public String[] selectImports(AnnotationMetadata importingClassMetadata) {
        //讀取EnableServer中全部的屬性方法,本例中僅有type()屬性方法
        //其中key爲屬性方法的名稱,value爲屬性方法的返回對象
        Map<String,Object> annotationAttributes = importingClassMetadata
                .getAnnotationAttributes(EnableServer.class.getName());
        //獲取名爲type的屬性方法,而且強制轉換成Server.Type類型
        Server.Type type = (Server.Type) annotationAttributes.get("type");
        //導入的類名稱數組
        String[] importClassNames = new String[0];
        switch (type) {
            case HTTP:
                importClassNames = new String[]{HTTPServer.class.getName()};
                break;
            case FTP:
                importClassNames = new String[]{FTPServer.class.getName()};
                break;
        }
        return importClassNames;
    }
}

標註@EnableServer到引導類EnableServerBootstrap

@Configuration
@EnableServer(type = Server.Type.HTTP)
public class EnableServerBootstrap {
    public static void main(String[] args) {
        //構建Annotation配置驅動Spring上下文
        AnnotationConfigApplicationContext context = new
                AnnotationConfigApplicationContext();
        //註冊當前引導類(被@Configuration標註)到Spring上下文
        context.register(EnableServerBootstrap.class);
        //啓動上下文
        context.refresh();
        //獲取Server Bean對象,實際爲HttpServer
        Server server = context.getBean(Server.class);
        //啓動服務器
        server.start();
        //關閉服務器
        server.stop();
    }
}

運行結果(部分)

16:52:08.966 [main] DEBUG org.springframework.context.annotation.AnnotationConfigApplicationContext - Unable to locate LifecycleProcessor with name 'lifecycleProcessor': using default [org.springframework.context.support.DefaultLifecycleProcessor@2fb3536e]
16:52:08.967 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Returning cached instance of singleton bean 'lifecycleProcessor'
16:52:08.975 [main] DEBUG org.springframework.core.env.PropertySourcesPropertyResolver - Could not find key 'spring.liveBeansView.mbeanDomain' in any property source
16:52:08.979 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Returning cached instance of singleton bean 'com.cloud.demo.server.HTTPServer'
HTTP服務器啓動中...
HTTP服務器關閉中...

基於ImportBeanDefinitionRegistrar接口實現

替換上例中的ServerImportSelector便可

public class ServerImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar {
    @Override
    public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
        //複用 {@link ServerImportSelector} 實現,避免重複勞動
        ImportSelector importSelector = new ServerImportSelector();
        //篩選Class名稱集合
        String[] selectedClassNames = importSelector.selectImports(importingClassMetadata);
        //建立Bean定義
        Stream.of(selectedClassNames)
                //轉化爲BeanDefinitionBuilder對象
                .map(BeanDefinitionBuilder::genericBeanDefinition)
                //轉化爲BeanDefinition
                .map(BeanDefinitionBuilder::getBeanDefinition)
                //註冊BeanDefinition到BeanDefinitionRegistry
                .forEach(beanDefinition -> BeanDefinitionReaderUtils
                        .registerWithGeneratedName(beanDefinition,registry));
    }
}

替換@EnableServer的@Import

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import(ServerImportBeanDefinitionRegistrar.class)
public @interface EnableServer {
    /**
     * 設置服務器類型
     * @return
     */
    Server.Type type();
}

運行結果

17:38:53.147 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Returning cached instance of singleton bean 'lifecycleProcessor'
17:38:53.150 [main] DEBUG org.springframework.core.env.PropertySourcesPropertyResolver - Could not find key 'spring.liveBeansView.mbeanDomain' in any property source
17:38:53.152 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Returning cached instance of singleton bean 'com.cloud.demo.server.HTTPServer#0'
HTTP服務器啓動中... HTTP服務器關閉中...

相關文章
相關標籤/搜索