feat: enhance @PostConstruct with order and @Qualifier for fields

- Add value() to @PostConstruct for execution order control
- Allow @Qualifier on fields for use with @Inject
- Sort @PostConstruct methods by inheritance depth then order value

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
Timi
2026-01-15 18:36:18 +08:00
parent 597065badc
commit e3226f2647
3 changed files with 27 additions and 5 deletions

View File

@ -253,22 +253,37 @@ public class BeanScanner {
}
private List<Method> findPostConstructs(Class<?> clazz) {
List<Method> methods = new ArrayList<>();
// 收集所有 @PostConstruct 方法及其元数据继承深度、order 值)
record PostConstructInfo(Method method, int depth, int order) {}
List<PostConstructInfo> collected = new ArrayList<>();
Class<?> currentClass = clazz;
int depth = 0;
// 从当前类向上遍历到 Object收集所有 @PostConstruct 方法
while (currentClass != null && currentClass != Object.class) {
int currentDepth = depth;
for (Method method : currentClass.getDeclaredMethods()) {
if (method.isAnnotationPresent(PostConstruct.class)) {
if (method.getParameterCount() != 0) {
throw new InjectException("@PostConstruct method must have no parameters: %s".formatted(method.getName()));
}
// 添加到列表头部,确保父类方法先执行
methods.addFirst(method);
int order = method.getAnnotation(PostConstruct.class).value();
collected.add(new PostConstructInfo(method, currentDepth, order));
}
}
currentClass = currentClass.getSuperclass();
depth++;
}
return methods;
// 先按继承深度降序(父类深度大,先执行),同层级内按 order 升序
collected.sort((a, b) -> {
int depthCompare = Integer.compare(b.depth, a.depth);
if (depthCompare != 0) {
return depthCompare;
}
return Integer.compare(a.order, b.order);
});
return collected.stream().map(PostConstructInfo::method).toList();
}
}

View File

@ -13,4 +13,11 @@ import java.lang.annotation.Target;
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface PostConstruct {
/**
* 执行顺序,数值越小越先执行,默认为 0
*
* @return 执行顺序
*/
int value() default 0;
}

View File

@ -10,7 +10,7 @@ import java.lang.annotation.Target;
*
* @author 夜雨
*/
@Target(ElementType.PARAMETER)
@Target({ElementType.PARAMETER, ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
public @interface Qualifier {