背景:在工作会遇到,自己写的服务,想被别人引用,引用方引用你的工程稍微简单的做法是,在启动时,扫描路径加上被引用服务的包的注解路径,才能被调用,复杂的就需要加的配置更多了,有没有通过一个简单的注解,就可以调用被引用服务?
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来实现注解类启动服务的,这个网上已有例子,可以自行搜索。