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

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值