简体   繁体   English

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

[英]Make Spring Boot Scan for different Annotations

To utilize the full power of spring magic, annotate your active components with @Component or any derived annotation, lean back and relax while Spring wires together your application.要利用 spring 魔法的全部力量,请使用@Component或任何派生的注释来注释您的活动组件,在 Spring 将您的应用程序连接在一起时向后靠并放松。

Sofar so good.到现在为止还挺好。

Now I want to structure my app according to the Clean Architecture/Hexagonal Architecture pattern, and desire to keep Spring away from my inner circle, the domain.现在我想根据 Clean Architecture/Hexagonal Architecture 模式构建我的应用程序,并希望让 Spring 远离我的核心圈,即域。 To achive that, I could simply drop the spring magic and create a couple of @Configuration -classes with some @Bean -providing methods.为了实现这一点,我可以简单地放弃 spring 魔法并使用一些@Bean提供方法创建几个@Configuration类。
That is, creating a lot of boilerplate code and the necessity of having enough domain knowledge to configure everything - so not, what I want.也就是说,创建大量样板代码以及拥有足够的领域知识来配置所有内容的必要性 - 所以不是我想要的。

What I want: I want to annotate my domain types with annotations like @UseCase , @Port , @Service , @Entity , @EntityId , @ValueObject and other meaningfull annotations, carrying the domain knowledge and intent regarding those classes - and use as much spring magic as possible in the outer layer, to automate the configuration, drawing necessary knowledge as declared in the domain layer.我想:我想我的注释域类型与像注释@UseCase@Port@Service@Entity@EntityId@ValueObject等meaningfull注解,携带关于这些类的领域知识和意图-和使用尽可能多的spring magic 在外层尽可能地自动化配置,绘制域层中声明的必要知识。

I could do that, hiding the Spring Dependency by hiding an @Component -Annotation within the @UseCase -Annotation, but then I my domain part would still be spring dependent - just with some indirection.我可以做到这一点,通过在@UseCase -Annotation 中隐藏一个@Component -Annotation 来隐藏 Spring Dependency,但是我的域部分仍然依赖于 spring - 只是有一些间接性。

What I would prefer is, telling Spring to not look for @Component but for @UseCase instead.我更喜欢的是,告诉 Spring 不要查找@Component而是查找@UseCase My imagination tells me, Spring works somehow like this:我的想象力告诉我,Spring 的工作方式是这样的:

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

And I hope, it is possible to tell the method which does the check, whether the class has the @Component -Annotation to check wether it has some other, meaningful annotation, either by configuration or by extension.我希望,可以通过配置或扩展来告诉执行检查的方法,该类是否具有@Component -Annotation 以检查它是否具有其他有意义的注释。

However, I have no clue, what class and or method might be responsible for this task.但是,我不知道什么类和/或方法可能负责此任务。

Questions in short:问题简述:

  • Which class(es) are responsible for finding my @Component-annotated classes?哪个类负责查找我的 @Component 注释类?
  • (How) can I influence them to find @UseCase-annotated classes, where @UseCase does not include @Component? (如何)我可以影响他们找到 @UseCase 注释的类,其中 @UseCase 不包含 @Component?

Also feel free, to respectfully comment, why my idea is stupid.也随意,恭敬地评论,为什么我的想法是愚蠢的。 Thats always the most enlightening!那永远是最有启发性的!


This is in Response to the answer by @Ghokun which seems reasonable but fails这是对@Ghokun 的回答的回应,这似乎合理但失败了

My Example-Project has the following structure:我的示例项目具有以下结构:

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

NoComponentDemoApp.java: NoComponentDemoApp.java:

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

UseCaseScane.java用例扫描.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
{
}

SomeUseCase.java一些用例.java

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

UseCase.java用例.java

public @interface UseCase
{
}

Ofc.办公室when I enable default filters and mark SomeUseCase.java with @Component it works.当我启用默认过滤器并使用@Component标记SomeUseCase.java ,它可以工作。 But something fails.但有些事情失败了。 For brevity I removed import.为简洁起见,我删除了导入。 Package info can be deduced from the structure.可以从结构中推断出包信息。 If deemed necessary, I will add it.如果认为有必要,我会添加它。

Spring already gives you that option with the following configuration: 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 {}

Documentation link 文档链接


Edit:编辑:

It works with following configuration.它适用于以下配置。 Please check your classes:请检查您的课程:

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