在看swagger的源码的时候,发现swagger大量使用了spring-plugin,这个组件在其他地方并不常见,看了其Github:https://github.com/spring-projects/spring-plugin。被称为世界上最小的插件系统,看源码结构,可以看到确实很小,只有那么几个类而已:
下面用spring plugin写一个例子:
@Configuration @EnablePluginRegistries({Vehicle.class}) public class SpringPluginTestConfig { |
上面是配置类型
public interface Vehicle extends Plugin<Wether> { public void reachGoal(Wether wether); } |
Vehicle类是交通工具接口,继承了Plugin接口
public class Car implements Vehicle { @Override public void reachGoal(Wether wether) { supports(wether); System.out.println("汽车。。。"); } @Override public boolean supports(Wether delimiter) { return false; } } |
public class Plane implements Vehicle { @Override public void reachGoal(Wether wether) { System.out.println("飞机。。。"); } @Override public boolean supports(Wether delimiter) { return false; } } |
上面两个是定义的具体的交通工具:汽车、飞机。两个类都实现了Vehicle的工具。
@Autowired @Qualifier("vehicleRegistry") PluginRegistry<Vehicle, Wether> vehicleRegistry; @GetMapping("/checkPlugin") public void checkPlugin() { List<Vehicle> vehicles = vehicleRegistry.getPlugins(); Wether wether = new Wether(); for (Vehicle vehicle : vehicles) { vehicle.reachGoal(wether); } } |
通过自动注入vehicleRegistry,调用getPlugins方法就可以获取vehicle列表了。
plugin的源码
源码解析:
@Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) @Inherited @Documented @Import(PluginRegistriesBeanDefinitionRegistrar.class) public @interface EnablePluginRegistries { |
这个方法import了PluginRegistriesBeanDefinitionRegistrar
public class PluginRegistriesBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar { /* * (non-Javadoc) * @see org.springframework.context.annotation.ImportBeanDefinitionRegistrar#registerBeanDefinitions(org.springframework.core.type.AnnotationMetadata, org.springframework.beans.factory.support.BeanDefinitionRegistry) */ @Override public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) { Class<?>[] types = (Class<?>[]) importingClassMetadata.getAnnotationAttributes( EnablePluginRegistries.class.getName()).get("value"); //这里会获取@EnablePluginRegistries注解中的value,这里就是 for (Class<?> type : types) { BeanDefinitionBuilder builder = BeanDefinitionBuilder.rootBeanDefinition(PluginRegistryFactoryBean.class); builder.addPropertyValue("type", type); AbstractBeanDefinition beanDefinition = builder.getBeanDefinition(); Qualifier annotation = type.getAnnotation(Qualifier.class); // If the plugin interface has a Qualifier annotation, propagate that to the bean definition of the registry if (annotation != null) { AutowireCandidateQualifier qualifierMetadata = new AutowireCandidateQualifier(Qualifier.class); qualifierMetadata.setAttribute(AutowireCandidateQualifier.VALUE_KEY, annotation.value()); beanDefinition.addQualifier(qualifierMetadata); } // Default String beanName = annotation == null ? StringUtils.uncapitalize(type.getSimpleName() + "Registry") : annotation .value(); //这里就是对象的名字,我们的例子里就是vehicle+Registry = vehicleRegistry registry.registerBeanDefinition(beanName, builder.getBeanDefinition()); } } } |
通过这个方法,就动态注入了BeanDefinition,进而在后续创建bean的时候使用到。对应的plugin都是PluginRegistryFactoryBean创建的。