Spring Boot如何收集自定义注解标注的类并获取其实例?
该需求完全可实现,两种方案可以分别借助Spring提供的类路径扫描API、Spring上下文查询API实现,具体实现方式如下:
方案1:扫描注解类并手动实例化
使用Spring提供的ClassPathScanningCandidateComponentProvider类实现自定义类扫描,不需要依赖Spring托管实例,自行反射创建对象。
实现代码(MyAnnotationService.java中)
import org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider; import org.springframework.core.type.filter.AnnotationTypeFilter; import org.springframework.beans.factory.config.BeanDefinition; import java.util.ArrayList; import java.util.List; import java.util.Set; public class MyAnnotationService { public void scanAndInstantiate() throws Exception { // 初始化扫描器,false表示不使用Spring默认的@Component等注解过滤规则 ClassPathScanningCandidateComponentProvider scanner = new ClassPathScanningCandidateComponentProvider(false); // 添加自定义注解过滤规则,只扫描带@MyAnnotation的类 scanner.addIncludeFilter(new AnnotationTypeFilter(MyAnnotation.class)); // 指定要扫描的基础包,可配置为你项目的根包,比如"com.my.project" Set<BeanDefinition> candidateComponents = scanner.findCandidateComponents("com.my.project"); List<Object> instances = new ArrayList<>(); for (BeanDefinition bd : candidateComponents) { // 拿到类全限定名,反射实例化 Class<?> clazz = Class.forName(bd.getBeanClassName()); Object instance = clazz.getDeclaredConstructor().newInstance(); instances.add(instance); // 后续可以自行收集注解的name属性,组装成你需要的结构 } } }
注意事项
- 该方式创建的实例不归Spring容器管理,类内部的
@Autowired、@Value等Spring注解不会自动生效,仅适合无Spring依赖的简单类使用。
方案2:从Spring容器直接获取托管的注解实例
这是业务中实现策略模式最常用的方案,所有标注@MyAnnotation的类需要先添加@Component(或@Service等Spring组件注解)交给Spring托管,之后直接从上下文批量查询即可。
实现代码(MyAnnotationService.java中)
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.ApplicationContext; import org.springframework.core.annotation.AnnotationUtils; import javax.annotation.PostConstruct; import java.util.Map; import java.util.stream.Collectors; @Service public class MyAnnotationService { @Autowired private ApplicationContext applicationContext; private Map<String, Object> strategyMap; @PostConstruct public void initStrategyMap() { // 从容器中拿到所有带@MyAnnotation注解的Bean实例 Map<String, Object> annotationBeans = applicationContext.getBeansWithAnnotation(MyAnnotation.class); // 组装成key为注解name属性、value为实例的Map strategyMap = annotationBeans.values().stream() .collect(Collectors.toMap( bean -> AnnotationUtils.findAnnotation(bean.getClass(), MyAnnotation.class).name(), bean -> bean )); } // 后续业务方法可以直接根据name从strategyMap中拿对应实例使用 public Object getStrategy(String name) { return strategyMap.get(name); } }
注意事项
- 必须给所有
@MyAnnotation标注的实现类加上@Component等Spring组件注解,否则Spring不会托管该类,无法被扫描到。 - 该方式拿到的实例已经完成了所有Spring依赖注入,完全符合业务开发的使用要求。
内容的提问来源于stack exchange,提问作者user2354302
相关产品推荐
相关产品推荐

