我想实现类似于Spring Data的东西.
开发人员可以定义一些接口,向接口添加自定义注释以标记它们(我的代码将为接口创建代理实例)并通过@Autowire将它们用于必要的服务.
在spring初始化期间,我需要获得所有接口的列表(正确注释)<为接口创建动态代理并将它们注入必要的位置.
代理创建,创建bean注入很好.现在的问题是:
如何查找所有接口的列表?
它们可以放在任何包装中(或者甚至放在一个单独的罐子里)并且有任何名称.扫描类路径上存在的所有类需要太多时间.
我找到了the question,但它需要基础包才能启动.
试过一个基于思考的解决方案,但它再次需要基础包或者从root开始需要非常大的时间来扫描所有可用的类.
Reflections reflections = new Reflections("...");
Set
所以我需要一个完整的基础包列表Spring扫描在包中找到我的接口(必须要快得多).
信息在SpringContext中绝对可用.我试图调试并看看basePackages []是如何初始化的,但是有很多私有类/方法用于初始化,我只是没有看到如何从ApplicationContext正确访问basePackages.
解决方案1:春天的方式
最简单的答案是遵循spring子项目(引导,数据……)如何实现这种类型的要求.它们通常定义一个自定义组合注释,该注释启用该功能并定义一组要扫描的包.
例如,给出这个注释:
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Import({MyInterfaceScanRegistrar.class})
public @interface MyInterfaceScan {
String[] value() default {};
}
其中value定义要扫描的包,而@Import启用MyInterfaceScan检测.
然后创建ImportBeanDefinitionRegistrar
.这个类将能够创建bean定义
Interface to be implemented by types that register additional bean
definitions when processing @Configuration classes. Useful when
operating at the bean definition level (as opposed to @Bean
method/instance level) is desired or necessary.
public class MyInterfaceScanRegistrar implements ImportBeanDefinitionRegistrar,EnvironmentAware {
private Environment environment;
@Override
public void setEnvironment(Environment environment) {
this.environment = environment;
}
@Override
public void registerBeanDefinitions(AnnotationMetadata metadata,BeanDefinitionRegistry registry) {
// Get the MyInterfaceScan annotation attributes
Map
这是逻辑的核心. bean定义可以被操作并重新定义为具有属性的bean工厂,或者使用来自接口的生成类重新定义.
MyCustomBean是一个简单的注释:
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface MyCustomBean {
}
哪个可以注释一个接口:
@MyCustomBean
public interface Class1 {
}
解决方案2:提取组件扫描
提取@ComponentScan中定义的包的代码会更复杂.
你应该创建一个BeanDefinitionRegistryPostProcessor并模仿ConfigurationClassPostProcessor:
>使用具有ComponentScan属性的声明类(例如,从ConfigurationClassPostProcessor中提取)迭代bean注册表以获取bean定义:
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) {
List
>像Spring一样提取这些属性
Set
>然后扫描包并注册bean定义,就像第一个解决方案一样