我想实现一些类似于Spring数据的东西。
在spring初始化期间,我需要获得所有接口的列表(适当地注释)<为接口创建动态代理,并将它们注入到需要的地方。
代理创建,创建bean注入就可以了。现在问题来了:
如何找到所有接口的列表?
Reflections reflections = new Reflections("...");
Set<Class<?>> annotated = reflections.getTypesAnnotatedWith(<annotation>);
因此,我需要一个基本包的完整列表,通过Spring扫描在包中找到我的接口(必须快得多)。
在SpringContext中肯定可以获得这些信息。我试图调试并查看basePackages[]是如何初始化的,但是有很多私有类/方法用于初始化,我只是不知道如何从ApplicationContext正确地访问basePackages。
解决方案1:Spring的方式
最简单的答案是了解spring子项目(引导、数据...)实现这种类型的需求。他们通常定义一个自定义的组合注释来启用该特性,并定义一组要扫描的包。
例如,给定以下注释:
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Import({MyInterfaceScanRegistrar.class})
public @interface MyInterfaceScan {
String[] value() default {};
}
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<String, Object> annotationAttributes = metadata.getAnnotationAttributes(MyInterfaceScan.class.getCanonicalName());
if (annotationAttributes != null) {
String[] basePackages = (String[]) annotationAttributes.get("value");
if (basePackages.length == 0){
// If value attribute is not set, fallback to the package of the annotated class
basePackages = new String[]{((StandardAnnotationMetadata) metadata).getIntrospectedClass().getPackage().getName()};
}
// using these packages, scan for interface annotated with MyCustomBean
ClassPathScanningCandidateComponentProvider provider = new ClassPathScanningCandidateComponentProvider(false, environment){
// Override isCandidateComponent to only scan for interface
@Override
protected boolean isCandidateComponent(AnnotatedBeanDefinition beanDefinition) {
AnnotationMetadata metadata = beanDefinition.getMetadata();
return metadata.isIndependent() && metadata.isInterface();
}
};
provider.addIncludeFilter(new AnnotationTypeFilter(MyCustomBean.class));
// Scan all packages
for (String basePackage : basePackages) {
for (BeanDefinition beanDefinition : provider.findCandidateComponents(basePackage)) {
// Do the stuff about the bean definition
// For example, redefine it as a bean factory with custom atribute...
// then register it
registry.registerBeanDefinition(generateAName() , beanDefinition);
System.out.println(beanDefinition);
}
}
}
}
}
MyCustomBean
是一个简单的注释:
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface MyCustomBean {
}
它可以注释接口:
@MyCustomBean
public interface Class1 {
}
解决方案2:提取组件扫描
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) {
List<BeanDefinitionHolder> configCandidates = new ArrayList<BeanDefinitionHolder>();
String[] candidateNames = registry.getBeanDefinitionNames();
for (String beanName : candidateNames) {
if (ConfigurationClassUtils.checkConfigurationClassCandidate(beanDef, this.metadataReaderFactory)) {
// Extract component scan
}
}
}
像Spring那样提取这些属性
Set<AnnotationAttributes> componentScans = AnnotationConfigUtils.attributesForRepeatable(
sourceClass.getMetadata(), ComponentScans.class, ComponentScan.class);
然后像第一个解决方案一样扫描包并注册bean定义
问题内容: 到目前为止,我使用PyQt类所做的事情: 输出: 使用: 输出: 有没有办法区分它们? 可以使用普通的Python代替PyQt类吗? 如何获得IPv6地址? 问题答案: 您应该使用netifaces。它被设计为跨平台的,并且包含Windows专用代码以及可在不同UNIX / UNIX类平台上工作的各种通用版本。 从netifaces版本0.10.0开始,支持Python3。 使用摘要
问题内容: 我可以想到两种方式: 惯用的方式是什么?也许已经有一个库函数可以完全满足我的需求? 问题答案: 我猜这种方式(或至少是另一种方式)更有效: 由于该函数与完全兼容,因为它需要并返回。不执行自动装箱。 我也在寻找一个等价的,我希望写一个等价的您的方法: 但是他们没有提供这种方法。不知道为什么。
我定义了一个配置,其中包含每个表的列列表,用作dedup键 例如:配置1: 这些列需要用作重复数据消除键。这个列表是动态的,有些表中有1个值,有些表中有2或3个值 我想做的是从这个列表中建立一个键列 我如何使这个动态的列表适用于任意数量的列。我试过这么做 为了实现这一点,我必须将列表转换为Df,列表中的每个值都需要在单独的列中,我无法理解这一点。 试过这么做但没用 欢迎任何意见,谢谢
基本信息 Path: /api/interface/list_menu Method: GET 接口描述: 请求参数 Headers 参数名称 参数值 是否必须 示例 备注 Content-Type application/json 是 Query 参数名称 是否必须 示例 备注 project_id 是 token 是 返回数据 { "errcode": 0, "errmsg": "成功
基本信息 Path: /api/interface/list Method: GET 接口描述: 请求参数 Headers 参数名称 参数值 是否必须 示例 备注 Content-Type application/json 是 Query 参数名称 是否必须 示例 备注 project_id 是 token 是 page 是 1 当前页数 limit 是 10 每页数量,默认为10,如果不想要分页
问题内容: 为了确定给定类型是否使用reflect包实现接口,您需要将reflect.Type传递给reflect.Type.Implements()。您如何获得这些类型之一? 作为一个例子,试图获得未初始化的os.Error(接口)类型的类型并 没有 工作(它恐慌的时候,你要调用它的种类()) 问题答案: 像这样做: 或一行: