SpringBoot手动装配,自定义Enable模块
前言
前面我们介绍了简单详细的SpringBoot自动配置原理解析,今天这篇文章主要是介绍下如何是实现手动配置,自定义Enable模块,
基于注解驱动实现
基于注解的驱动实现是最基本的自定义Enable模块,它是不带条件的装配。首先我们来看看如何来实现!
第一步: 定义好配置类
这里定义了配置类SayHelloWorldConfiguration
public class SayHelloWorldConfiguration {
@Bean
SayHelloWorld sayHelloWorld() {
System.out.println("********加载HelloConfig");
return new SayHelloWorld();
}
}
这里就是实例化SayHelloWorld类,添加@Bean
注解表明该方法实例化的对象会被加载到IOC容器之中。
第二步:定义EnableXXX注解
这里定义EnableHello注解,并且通过@Import
注解将SayHelloWorldConfiguration配置类导入并加载到IOC容器。
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE})
@Documented
//引入HelloConfig配置类
@Import({SayHelloWorldConfiguration.class})
public @interface EnableHello {
}
第三步:在SpringBoot的启动类上添加Enable注解
至此基于注解驱动的手动配置就好了。启动之后我们就可以拿到实例化后的SayHelloWorld对象。但是,他这个是不能带任何条件的。
基于选择器实现的手动配置
与基于注解驱动的不同的是,基于选择器实现的手动配置需要增加一个选择器。步骤如下:
第一步 自定义选择器,实现ImportSelector
public class HelloWorldImportSelector implements ImportSelector {
@Override
public String[] selectImports(AnnotationMetadata annotationMetadata) {
//获取注解上的属性
Map<String, Object> annotationAttributes = annotationMetadata.getAnnotationAttributes(EnableSelectorHelloWorld.class.getName());
Boolean isLinux = (Boolean) annotationAttributes.get("isLinux");
return new String[]{isLinux ? SayHelloWorldConfiguration.class.getName() : SayHelloWorldConfiguration2.class.getName()};
}
}
这个选择器可以根据注解中传入的参数,返回不同的配置类,如上,当注解中的isLinux为true时,返回的配置类是SayHelloWorldConfiguration,否则,返回的配置类是SayHelloWorldConfiguration2
第二步:定义Enable注解
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import({HelloWorldImportSelector.class})
public @interface EnableSelectorHelloWorld {
boolean isLinux();
}
这里引入的是我们前面定义的选择器类。
后面的步骤跟基于注解驱动实现一致,在此就不在赘述了。
条件装配
如果某些配置类需要满足一定的条件才能启动,该如何实现呢?这就需要用到条件装配了。条件装配的配置步骤如下:
第一步:定义Condition的实现类
public class OnSystemPropertyCondition implements Condition {
@Override
public boolean matches(ConditionContext conditionContext, AnnotatedTypeMetadata annotatedTypeMetadata) {
//获取注解属性
Map<String, Object> attrs = annotatedTypeMetadata.getAnnotationAttributes(ConditionalOnSystemProperty.class.getName());
//获取系统值
String system = String.valueOf(attrs.get("value"));
String currentOs = System.getProperty("os.name");
boolean result = currentOs.contains(system);
System.out.println("********currentOs=" + currentOs + "匹配结果是=" + result);
return result;
}
}
这里的代码也比较简单,就是根据ConditionalOnSystemProperty注解传入的value值,是否包含在当前系统的系统名中,如果是的话则返回true。否则,返回false。返回true的话,则会加载配置类中通过@Bean
定义的对象。
第二步:定义配置类
public class SayHelloWorldConfiguration2 {
/**
* @return
*/
@ConditionalOnSystemProperty(value = "Windows")
@Bean
SayHelloWorld sayHelloWorld() {
System.out.println("*********开始装配SayHelloWorld");
return new SayHelloWorld();
}
}
定义Enable注解
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE})
@Documented
@Import({SayHelloWorldConfiguration2.class})
public @interface EnableConditionHelloWorld {
}
总结
手动装配其实也是很简单的。上面就简单的示例了三种情况下的装配。希望对读者朋友们有所帮助。
源码下载
源码下载
作者:码农飞哥
微信公众号:码农飞哥