Spring Boot自定義@Enable模塊驅動

Spring Boot自定義@Enable模塊驅動

註解驅動

​ 先看下Spring Framework已有的實現,@EnableWebMvc

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

@Import({DelegatingWebMvcConfiguration.class}),引用了DelegatingWebMvcConfiguration類。

@Configuration
public class DelegatingWebMvcConfiguration extends WebMvcConfigurationSupport {
  ...
}

​ 可以看出,DelegatingWebMvcConfiguration只是一個@Configuration類。

​ 接下來實現我們自己@Enable模塊驅動

自定義@Configuration類

@Configuration
public class HelloWorldConfiguration {

    @Bean
    public String helloWorld() {
        return "hello world";
    }
}

實現@EnableHelloWorld

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

自定義啓動類

@EnableHelloWorld
@Configuration
public class EnableHelloWorldBootStrap {
    public static void main(String[] args) {
      	//構建Spring上下文
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
      	//將當前引導類註冊到Spring中
        context.register(EnableHelloWorldBootStrap.class);
      	//啓動
        context.refresh();
      	//獲取名稱爲helloWorld的Bean
        String helloWorld = context.getBean("helloWorld", String.class);
        System.out.println("helloWorld = " + helloWorld);
    }
}

​ 這樣我們就基於註解實現了模塊驅動。

接口驅動

基於接口進行實現,需要實現ImportSelector或者ImportBeanDefinitionRegistrar接口

實現ImportSelector

​ 假設學校裏有學生和老師,Student和Teacher,通過@EnablePeople來設置人員類型。

定義接口

public interface People {
    void work();


    enum Type {
        /**
         * 學生
         */
        STUDENT,
        /**
         * 老師
         */
        TEACHER,
    }
}

實現StudentPeople和TeacherPeople

/**
 * 遵循約定,確保是spring的組件。
 */
@Component
public class StudentPeople implements People {
    @Override
    public void work() {
        System.out.println("這是學生在工作");
    }
}
/**
 * 遵循約定,確保是spring的組件。
 */
@Component
public class TeacherPeople implements People {
    @Override
    public void work() {
        System.out.println("這是老師在工作");
    }
}

定義@EnablePeople

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import(PeopleImportSelector.class)
public @interface EnablePeople {
    People.Type type();
}

實現PeopleImportSelector

public class PeopleImportSelector implements ImportSelector {
    @Override
    public String[] selectImports(AnnotationMetadata importingClassMetadata) {
        //讀取EnablePeople中所有的屬性方法
        Map<String, Object> annotationAttributes = importingClassMetadata.getAnnotationAttributes(EnablePeople.class.getName());
        People.Type type = (People.Type) annotationAttributes.get("type");
        //導入的類名稱數組
        String[] importClassNames = new String[0];
        switch (type) {
            case STUDENT:
                importClassNames = new String[]{StudentPeople.class.getName()};
                break;
            case TEACHER:
                importClassNames = new String[]{TeacherPeople.class.getName()};
                break;
            default:
                break;
        }
        return importClassNames;
    }
}

創建啓動類

@Configuration
@EnablePeople(type = People.Type.STUDENT)
public class BootStrap {
    public static void main(String[] args) {
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
        context.register(BootStrap.class);
        context.refresh();
        People bean = context.getBean(People.class);
        bean.work();
    }
}
這是學生在工作

得到了我們想要的結果,然後將STUDENT修改爲TEACHER,

這是老師在工作

實現ImportBeanDefinitionRegistrar

其它與實現ImportSelector一致。

實現ImportBeanDefinitionRegistrar接口

public class PeopleImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar {
    @Override
    public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
        //讀取EnablePeople中所有的屬性方法
        Map<String, Object> annotationAttributes = importingClassMetadata.getAnnotationAttributes(EnablePeople.class.getName());
        People.Type type = (People.Type) annotationAttributes.get("type");
        //導入的類名稱數組
        String[] importClassNames = new String[0];
        switch (type) {
            case STUDENT:
                importClassNames = new String[]{StudentPeople.class.getName()};
                break;
            case TEACHER:
                importClassNames = new String[]{TeacherPeople.class.getName()};
                break;
            default:
                break;
        }
        Stream.of(importClassNames)
                //轉化爲BeanDefinitionBuilder對象
                .map(BeanDefinitionBuilder::genericBeanDefinition)
                //轉化爲BeanDefinition
                .map(BeanDefinitionBuilder::getBeanDefinition)
                //註冊到BeanDefinitionRegistry
                .forEach(beanDefinition ->
                        BeanDefinitionReaderUtils.registerWithGeneratedName(beanDefinition, registry));
    }
}

修改@EnablePeople導入類

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import(PeopleImportBeanDefinitionRegistrar.class)
public @interface EnablePeople {
    People.Type type();
}

重新啓動,觀察結果。一切正常。

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