用@ComponentScan元注释的Spring自定义@Enable注释

问题描述 投票:4回答:1

我正在尝试为Spring框架编写我自己的@Enable批注,该批注应如下使用:

package com.example.package.app;

@SpringBootApplication
@com.example.annotations.EnableCustom("com.example.package.custom")
public class MyApplication {}

我关注了Component scan using custom annotation,但这带来了一些限制:

  1. 我无法使基本包属性动态化,即,我无法传递"com.example.package.base",但需要在配置中预定义包。

    我看过@AliasFor,但无法正常工作。

  2. 当我忽略基本包时,扫描从注释的定义包开始,而不是从已注释类的包开始。在上面的示例中,它将仅扫描并创建com.example.annotations中类的bean,而不扫描com.example.package.*中的类。

    我看了在EntityScanPackages.Registrar.class批注中导入的@EntityScan,但这是一个内部类,我的批注无法导入。

[如果我将@ComponentScan(includeFilters = @ComponentScan.Filter(type = FilterType.ANNOTATION, value = MyAnnotation.class))放在MyApplication类上,则一切正常,但是当将其移到@EnableCustom的元注释时,它将停止工作。如何告诉Spring Framework将@EnableCustom考虑为以一些默认值指定@ComponentScan的另一种方式。我尝试使用@Configuration@Component和其他元素进行元注释,但无济于事:

@Configuration
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@ComponentScan(
        includeFilters = @ComponentScan.Filter(
                type = FilterType.ANNOTATION,
                value = ApplicationService.class))
public @interface EnableApplicationServices {
    @AliasFor(annotation = ComponentScan.class, attribute = "basePackages")
    String[] value() default {};
}

我在哪里可以找到有关此文档的文档,或者您建议什么起点?我的长期目标是要有一个Spring Boot入门程序,可以供许多项目使用。


可以在以下存储库中找到一个M(N)WE:https://github.com/knittl/stackoverflow/tree/spring-enable-annotation

这里是程序包结构的摘要:

// com.example.annotations.EnableCustom.java
@Configuration
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
// this annotation is never honored:
@ComponentScan(
        includeFilters = @ComponentScan.Filter(
                type = FilterType.ANNOTATION,
                value = MyAnnotation.class))
//@Import(EnableCustom.EnableCustomConfiguration.class)
public @interface EnableCustom {
    // this annotation works in combination with @Import, but scans the wrong packages.
    @ComponentScan(
            includeFilters = @ComponentScan.Filter(
                    type = FilterType.ANNOTATION,
                    value = MyAnnotation.class))
    class EnableCustomConfiguration {}
}

// file:com.example.app.Application.java
@SpringBootApplication
@EnableCustom("com.example.app.custom.services")
// @ComponentScan(
//         includeFilters = @ComponentScan.Filter(
//                 type = FilterType.ANNOTATION,
//                 value = MyAnnotation.class)) // <- this would work, but I want to move it to a custom annotation
public class Application {
}

// file:com.example.app.custom.services.MyService
@MyAnnotation
public class MyService {
    public MyService() {
        System.out.println("Look, I'm a bean now!");
    }
}

// file:com.example.annotations.services.WrongService.java
@MyAnnotation
public class WrongService {
    public WrongService() {
        System.out.println("I'm in the wrong package, I must not be instantiated");
    }
}
java spring spring-annotations component-scan spring-autoconfiguration
1个回答
0
投票

使用自定义注释@EnableAnnotation和basePackages属性

@EnableAnnotation(basePackages =  "write-here-a-base-package")
@Configuration
@EnableAutoConfiguration
@ComponentScan
public class SampleSimpleApplication implements CommandLineRunner {

  public static void main(String[] args) throws Exception {
   SpringApplication.run(SampleSimpleApplication.class, args);
  }
}

@@ EnableAnnotation的定义如下:

@Retention(RUNTIME)
@Target(TYPE)
@Import(EnableAnnotationConfigRegistrar.class)
public @interface EnableAnnotation {

  String[] basePackages() default "*";

  @AliasFor(annotation = Import.class, attribute = "value")
  Class<?>[] value() default { EnableAnnotationConfigRegistrar.class };

}

最后,EnableAnnotationConfigRegistrar.class以编程方式进行扫描:

public class EnableAnnotationConfigRegistrar implements ImportBeanDefinitionRegistrar {

 @Override
 public void registerBeanDefinitions(AnnotationMetadata enableAnnotationMetadata,
  BeanDefinitionRegistry registry) {
   AnnotationAttributes enableAnnotationAttributes = new AnnotationAttributes(
   enableAnnotationMetadata.getAnnotationAttributes(EnableAnnotation.class.getName()));

   String[] basePackages = enableAnnotationAttributes.getStringArray("basePackages");
   AnnotationConfigApplicationContext annotationConfigApplicationContext = new AnnotationConfigApplicationContext(basePackages);
   }

}
© www.soinside.com 2019 - 2024. All rights reserved.