当前位置: 首页 > 知识库问答 >
问题:

Spring类路径组件扫描

平学
2023-03-14

我需要为类构建映射(字面上是映射)

@Inherited
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface Mapping {
     String value();
}

和:

public class MappingLookUp {
    private static final Map<Class<?>, String> MAPPING_LOOK_UP;
    static {
        Map<Class<?>, String> lookUp = new HashMap<>();
        ClassPathScanningCandidateComponentProvider scanningCandidateComponentProvider = new ClassPathScanningCandidateComponentProvider(false);
        scanningCandidateComponentProvider.addIncludeFilter(new AnnotationTypeFilter(Mapping.class));
        for (BeanDefinition beanDefinition : scanningCandidateComponentProvider.findCandidateComponents("blah")) {
            Class<?> clazz;
            try {
                clazz = Class.forName(beanDefinition.getBeanClassName());
            } catch (ClassNotFoundException e) {
                throw new RuntimeException(e);
            }
            Mapping mapping = AnnotationUtils.getAnnotation(clazz, Mapping.class);
            if (mapping == null) {
                throw new IllegalStateException("This should never be null");
            }
            lookUp.put(clazz, mapping.value());
        }
        MAPPING_LOOK_UP = Collections.unmodifiableMap(lookUp);
    }

    public static String getMapping(Class<?> clazz) {
        ...
    }
}

虽然我相信这会起作用,但这感觉就像:

  1. 静态初始化需要投入大量精力。
  2. 对扫描组件提供商的恶意使用,尽管通常推荐用于此目的BeanDefinition使它听起来像是用于查找Spring Bean,而不是一般的类定义

需要明确的是,带注释的值是数据类 - 而不是Spring管理的bean - 所以BeanPostProcessor模式不适合,事实上,这就是为什么使用扫描组件提供程序感觉很尴尬的原因,对我来说,它似乎是为了发现Spring管理的Bean。

这是实现这种模式的正确方式吗?是提供商的正当应用吗?在不引入其他类路径扫描实现的情况下,有没有可行的替代方案?


共有2个答案

蒙麒
2023-03-14

最近我问了一个非常类似的问题:如何从@ComponentScan包中获取接口列表,并最终实现了建议的第一种方法。

你可以看到代码https://github.com/StanislavLapitsky/SpringSOAProxy看到https://github.com/StanislavLapitsky/SpringSOAProxy/blob/master/core/src/main/java/org/proxysoa/spring/service/ProxyableScanRegistrar.java当然还有初始化注释https://github.com/StanislavLapitsky/SpringSOAProxy/blob/master/core/src/main/java/org/proxysoa/spring/annotation/ProxyableScan.java关键是添加@导入({ProxyableScanRegistrar.class})

关键代码是

public class ProxyableScanRegistrar 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 ProxyableScan annotation attributes
        Map<String, Object> annotationAttributes = metadata.getAnnotationAttributes(ProxyableScan.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()};
            }
濮佑运
2023-03-14

我建议这看起来不像是以一种非常Spring的方式完成的。

如果我要这样做,我会使用Spring的BeanPostProcessor或BeanFactoryPostProcessor。这两者都允许对Spring的BeanFactory中的所有Bean进行自省,并允许您摆脱当前设置的静态性,因为后处理器就是Spring Bean本身。

class MappingLookup implements BeanPostProcessor {
  private final Map<Class<?>, String> lookup = new HashMap<>();

  @Override
  public Object postProcessAfterInitialization(Object bean, String beanName) {
    // check bean's class for annotation...
    // add to lookup map as necessary...
    // make sure to return bean (javadoc explains why)
    return bean;
  }

  public String getMapping(Class<?> clazz) {
    // ...
  }

  // omitted other methods...
}
 类似资料:
  • 在Spring Boot应用程序中,我对@Entity类进行类路径扫描的所有尝试都失败了。我在网上找到的最常见的解决方案是这样的,但它不起作用-

  • 在这里的Spring Boot文档中,关于服务静态内容,它说: 默认情况下,Spring Boot将从类路径中名为/static(或/public或/resources或/META-INF/resources)的目录提供静态内容。 我发现目录中的所有内容: 将被复制到类路径中,因此我可以将我的静态内容放入: 一切都会很好,我很高兴,因为我可以将我的静态内容放在src目录下。 但是,我对此有一些疑问

  • 我似乎找不到任何关于在运行时扫描所有可用类(用于接口、注释等)是否仍然可行的信息,就像Spring、Reflections和许多其他框架和库当前所做的那样,面对与Jigsaw相关的类加载方式的更改。 编辑:这个问题是关于扫描实际的物理文件路径以查找类。另一个问题是动态加载类和资源。这是相关的,但不是重复的。 最新消息:Jetty项目已就此提出了一项标准化API的JEP提案。如果你有办法帮助实现这一

  • 问题内容: 面对Jigsaw的相关更改,我似乎找不到任何信息,以了解是否仍然可以在运行时扫描所有可用的类(用于接口,批注等),就像Spring,Reflections和当前其他许多框架和库那样。类的加载方式。 编辑 :此问题是关于 扫描 实际的物理文件路径以查找类。另一个问题是关于动态 加载 类和资源。它是相关的,但 绝不是重复的 。 更新 :Jetty项目已经为此制定了标准化API的 JEP提案

  • 我有一个eclipse java项目,在/src/main/java(包com.xxx.yyy)下。我还在/src/Test/java(包com.xxx.yyy)下有几个测试类。测试类(注释为@Service(value=“sampleclient”)公共类sampleclient{…}由位于/src/main/java下的一个包中的框架代码调用。 如果所有文件/包都位于/src/main/jav

  • 我找不到关于beans xml配置的文档,所以我在这里问:在 在概念上与Java中的包相同吗? 例如,在我的src/main/java(Eclipse中的项目资源管理器视图,平面包演示)中,假设我有4个包com.amazon、com.amazon.entities、com.amazon.services、com.amazon.repositories.在Navigator视图中,我只有“amazo