SpringBoot父类下的所有子类
SpringBoot父类下的所有子类
简要
今天在想为什么一些中间件我们只需要实现它指定的接口,这些中间件就会识别到我们自定义的类。。。比如SpringWeb中的WebMvcConfigurer? 其实这些中间件能识别我们的实现类是使用了反射原理;
那么在Spring项目中我们如何通过反射原理来实现指定类下面的子类呢?Spring提供了ClassPathScanningCandidateComponentProvider类,可以帮助我们从包路径中获取到所需的 BeanDefinition 集合,然后动态注册 BeanDefinition 到 BeanDefinitionRegistry,到达在容器中动态生成 Bean 的目的
主要函数
addIncludeFilter – 添加一个包含过滤器
addExcludeFilter – 添加一个排除过滤器
findCandidateComponents – 核心任务 : 从指定的某个包内扫描目标bean组件定义
resetFilters – 设置包含过滤器和排除过滤器为空
clearCache – 清除扫描过程中所记录的类的元数据信息缓存
具体实现:
ClassPathScanningCandidateComponentProvider provider = new ClassPathScanningCandidateComponentProvider(false);
provider.addIncludeFilter(new AssignableTypeFilter(FaterInterface.class));//查找某个类的子类
Set<BeanDefinition> sonclass = provider.findCandidateComponents("com.");//扫描指定包并返回子类
for (BeanDefinition s : sonclass) {
//可通过反射进行业务操作
Class<?> aClass = Class.forName(s.getBeanClassName());
}
例1
普通类实现父类下子类的创建,并注册到spring容器中;
配置类:
@Configuration
@Slf4j
public class CreateBeanAutoConfig {
@Bean
public void getSonClass() {
ClassPathScanningCandidateComponentProvider provider = new ClassPathScanningCandidateComponentProvider(false);
provider.addIncludeFilter(new AssignableTypeFilter(Father.class));
Set<BeanDefinition> components = provider.findCandidateComponents("com.");
for (BeanDefinition son : components) {
try {
Class<?> aClass = Class.forName(son.getBeanClassName());
log.info("子类:{}",aClass.getSimpleName());
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
}
}
public class Father {}//父类
public class Son extends Father{}//子类
例2
实现接口下子类方法参数不为null
@Configuration
@Slf4j
public class CreateBeanAutoConfig {
@Bean
public void getSonClass() throws ClassNotFoundException, IllegalAccessException, InstantiationException {
//扫描指定类在指定包下的实现类
ClassPathScanningCandidateComponentProvider provider = new ClassPathScanningCandidateComponentProvider(false);
provider.addIncludeFilter(new AssignableTypeFilter(Father.class));
Set<BeanDefinition> components = provider.findCandidateComponents("com.");
//为实现类的方法参数创建参数
for (BeanDefinition c: components) {
Class<?> aClass = Class.forName(c.getBeanClassName());
Father father = (Father)aClass.newInstance();
father.setName("张三");
}
}
}
public interface Father {
public void setName(String name);
}
@Configuration
@Slf4j
public class FatherImpl implements Father {
@Override
public void setName(String name) {
log.info("方法参数为:{}",name);
}
}
断点测试:可看出实现类中方法参数已经有参数了