我正在尝试为 Spring 框架编写自己的@Enable
注释,应按如下方式使用:
package com.example.package.app;
@SpringBootApplication
@com.example.annotations.EnableCustom("com.example.package.custom")
public class MyApplication {}
我使用自定义注释跟随组件扫描,但这带来了一些限制:
我无法使基础包属性动态化,即无法通过
"com.example.package.base"
,但需要在配置时预先定义包。我看了看
@AliasFor
,但无法让它工作。当我省略基本包时,扫描从注释的定义包开始,而不是从注释类的包开始。在上面的示例中,它只会为 中的类扫描和创建 bean
com.example.annotations
,而不会为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 启动器。
AM(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");
}
}