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();
}

重新启动,观察结果。一切正常。

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