繁体   English   中英

对不同的注解进行 Spring Boot 扫描

[英]Make Spring Boot Scan for different Annotations

要利用 spring 魔法的全部力量,请使用@Component或任何派生的注释来注释您的活动组件,在 Spring 将您的应用程序连接在一起时向后靠并放松。

到现在为止还挺好。

现在我想根据 Clean Architecture/Hexagonal Architecture 模式构建我的应用程序,并希望让 Spring 远离我的核心圈,即域。 为了实现这一点,我可以简单地放弃 spring 魔法并使用一些@Bean提供方法创建几个@Configuration类。
也就是说,创建大量样板代码以及拥有足够的领域知识来配置所有内容的必要性 - 所以不是我想要的。

我想:我想我的注释域类型与像注释@UseCase@Port@Service@Entity@EntityId@ValueObject等meaningfull注解,携带关于这些类的领域知识和意图-和使用尽可能多的spring magic 在外层尽可能地自动化配置,绘制域层中声明的必要知识。

我可以做到这一点,通过在@UseCase -Annotation 中隐藏一个@Component -Annotation 来隐藏 Spring Dependency,但是我的域部分仍然依赖于 spring - 只是有一些间接性。

我更喜欢的是,告诉 Spring 不要查找@Component而是查找@UseCase 我的想象力告诉我,Spring 的工作方式是这样的:

for (class in classpath-with-matching-package) {
    if (class has annotation '@Component') {
        createBeanDefinitionForClass(class)
    }
}
createBeansForDefinitions()

我希望,可以通过配置或扩展来告诉执行检查的方法,该类是否具有@Component -Annotation 以检查它是否具有其他有意义的注释。

但是,我不知道什么类和/或方法可能负责此任务。

问题简述:

  • 哪个类负责查找我的 @Component 注释类?
  • (如何)我可以影响他们找到 @UseCase 注释的类,其中 @UseCase 不包含 @Component?

也随意,恭敬地评论,为什么我的想法是愚蠢的。 那永远是最有启发性的!


这是对@Ghokun 的回答的回应,这似乎合理但失败了

我的示例项目具有以下结构:

src/main/java/de/mycorp/group
 |-> /exampleapp
   |-> NoComponentDemoApp.java
   |-> UseCaseScan.java
 |-> /springless
   |-> SomeUseCase.java
   |-> UseCase.java

NoComponentDemoApp.java:

@SpringBootApplication
public class NoComponentDemoApp
{
    public static void main(String[] args)
    {
        SpringApplication.run(NoComponentDemoApp.class, args);
    }
}

用例扫描.java

@Configuration
@ComponentScan(
         useDefaultFilters = false,
         includeFilters = {
                  @ComponentScan.Filter(UseCase.class)}, // type default/annotation, value synonym of classes
         basePackages = "de.mycorp.group.springless"
)
public class UseCaseScan
{
}

一些用例.java

@UseCase
public class SomeUseCase
{
    private static final Logger logger = LoggerFactory.getLogger(SomeUseCase.class);
    public SomeUseCase()
    {
        logger.info("Some Actor created");
    }
}

用例.java

public @interface UseCase
{
}

办公室当我启用默认过滤器并使用@Component标记SomeUseCase.java ,它可以工作。 但有些事情失败了。 为简洁起见,我删除了导入。 可以从结构中推断出包信息。 如果认为有必要,我会添加它。

Spring 已经通过以下配置为您提供了该选项:

import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.ComponentScan.Filter;
import org.springframework.context.annotation.FilterType;


@ComponentScan(useDefaultFilters = false,
               includeFilters = {@Filter(type = FilterType.ANNOTATION, class= UseCase.class)})
public class AppConfig {}

文档链接


编辑:

它适用于以下配置。 请检查您的课程:

package demo;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.ComponentScan.Filter;

@SpringBootApplication
@ComponentScan(useDefaultFilters = false, includeFilters = { @Filter(UseCase.class) })
public class DemoApplication {
    
    public static void main(String[] args) {
        SpringApplication.run(DemoApplication.class, args);
    }
    
}

package demo;

import javax.annotation.PostConstruct;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

@UseCase
public class AnnotatedClass {
    
    private static final Logger logger = LoggerFactory.getLogger(AnnotatedClass.class);
    
    @PostConstruct
    public void init() {
        logger.info("It Works!");
    }
}

package demo;

import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

import org.springframework.stereotype.Indexed;

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Indexed
public @interface UseCase {
    
}
...
2020-09-28 03:25:02.913  INFO 6829 --- [           main] demo.AnnotatedClass: It Works!
...

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM