使用@ComponentScan元注释的Spring自定义@Enable批注 [英] Spring custom @Enable annotation meta-annotated with @ComponentScan

查看:116
本文介绍了使用@ComponentScan元注释的Spring自定义@Enable批注的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I'm trying to write my own @Enable annotation for Spring framework, which should be used as follows:

package com.example.package.app;

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

我遵循了使用自定义注释进行组件扫描,但这存在一些限制:

I followed Component scan using custom annotation, but this poses several limitations:

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

  1. I cannot make the base package property dynamic, i.e. I cannot pass "com.example.package.base", but need to pre-define the package at the configuration.

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

I had a look at @AliasFor, but cannot get it to work.

当我忽略基本包时,扫描从注释的定义包开始,而不是从带注释的类的包开始.在上面的示例中,它只会为com.example.annotations中的类扫描并创建bean,而不会为com.example.package.*进行扫描.

When I leave out the base package, scanning starts from the defining package of the annotation, not from the package of the annotated class. In above's example, it would only scan and create beans for classes in com.example.annotations, but not for com.example.package.*.

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

I had a look at EntityScanPackages.Registrar.class which is imported in @EntityScan annotation, but it is an internal class and my annotation cannot import.

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

Everything works if I put @ComponentScan(includeFilters = @ComponentScan.Filter(type = FilterType.ANNOTATION, value = MyAnnotation.class)) on MyApplication class, but stops working when this is moved to a meta-annotation of @EnableCustom. How to tell Spring Framework to consider @EnableCustom as a different way of specifying @ComponentScan with some default values. I tried meta-annotating my annotation with @Configuration, @Component and others, to no avail:

@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启动器,该启动器可以供许多项目使用.

Where can I find documentation for this or what starting point would you recommend? My long term goal is to have a Spring Boot starter which can be used by a multitude of projects.

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

A M(N)WE can be found in the following repository: https://github.com/knittl/stackoverflow/tree/spring-enable-annotation

这是包装结构的简要说明:

Here's a rundown of the package structures:

// 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");
    }
}

推荐答案

使用具有 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 以编程方式进行扫描:

Finally, the EnableAnnotationConfigRegistrar.class scans programmatically:

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);
   }

}

这篇关于使用@ComponentScan元注释的Spring自定义@Enable批注的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆