背景:在工作會遇到,自己寫的服務,想被別人引用,引用方引用你的工程稍微簡單的做法是,在啓動時,掃描路徑加上被引用服務的包的註解路徑,才能被調用,複雜的就需要加的配置更多了,有沒有通過一個簡單的註解,就可以調用被引用服務?
springboot提供了很多註解,其中通過@import註解就可以實現自定義註解開啓服務的。其中有幾個類非常重要@import,ImportBeanDefinitionRegistrar,BeanRegistrationUtil。其中import這個註解是自定義類的入口,ImportBeanDefinitionRegistrar這個是spring提供的自定義類註冊的接口,必須實現此接口,BeanRegistrationUtil是類註冊的具體過程。詳細如下:
1,自定義啓動服務的註解,示例如下:
/**
* Function:開啓redis
*
* @author wangdong
*
*/
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@Import(RedisRegistry.class)
public @interface EnableRedis {
}
2,注入要導入的類,就是把開啓服務所需要的啓動配置文件都注入,示例如下:
public class RedisRegistry implements ImportBeanDefinitionRegistrar{
private final Logger logger = LoggerFactory.getLogger(this.getClass());
@Override
public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
if (logger.isInfoEnabled()) {
logger.info("RedisRegistry-registerBeanDefinitions begin to init redis configure");
}
BeanRegistrationUtil.registerBeanDefinitionIfNotExists(registry, RedisProperties.class.getName(),
RedisProperties.class);
........ //啓動所需要加載的配置文件都要註冊進來
}
}
3,注入工具類,BeanRegistrationUtil的定義:
public class BeanRegistrationUtil {
public static boolean registerBeanDefinitionIfNotExists(BeanDefinitionRegistry registry, String beanName,
Class<?> beanClass) {
return registerBeanDefinitionIfNotExists(registry, beanName, beanClass, null);
}
public static boolean registerBeanDefinitionIfNotExists(BeanDefinitionRegistry registry, String beanName,
Class<?> beanClass, Map<String, Object> extraPropertyValues) {
if (registry.containsBeanDefinition(beanName)) {
return false;
}
String[] candidates = registry.getBeanDefinitionNames();
for (String candidate : candidates) {
BeanDefinition beanDefinition = registry.getBeanDefinition(candidate);
if (Objects.equals(beanDefinition.getBeanClassName(), beanClass.getName())) {
return false;
}
}
BeanDefinition beanDefinition = BeanDefinitionBuilder.genericBeanDefinition(beanClass).getBeanDefinition();
if (extraPropertyValues != null) {
for (Map.Entry<String, Object> entry : extraPropertyValues.entrySet()) {
beanDefinition.getPropertyValues().add(entry.getKey(), entry.getValue());
}
}
registry.registerBeanDefinition(beanName, beanDefinition);
return true;
}
當上述完成後,引用者只需要在pom文件中加入工程依賴,然後在啓動類中加入@EnableRedis 就可以開啓redis的引用。
PS:RedisProperties裏面所需要的屬性配置在配置文件中都要有的。這個只是使用註解import類來實現註解類啓動服務,因爲在網上沒有搜到此方式的示例,所以分享一下大概的幾個類和流程;還有可以通過AOP來實現註解類啓動服務的,這個網上已有例子,可以自行搜索。