使用ClassPathBeanDefinitionScanner写一个包扫描

若要使用ClassPathBeanDefinitionScanner对象,必须一个BeanDefinitionRegistry作为入参传入
获取该对象的3种方法
1,通过一些BeanFactory的实现类,但是并不是所有BeanFactory都支持,默认ApplicationContext就不支持,强转又有风险。
2,通过Condition接口的方法,但是这样做太拖离Condition业务的本意。要在其上实现无关的扫描功能。
3,使用ImportBeanDefinitionRegistrar,也就是MyBatis与Spring整合的方式。(我原来最不想用这种方式,我想实现,在spring配置文件中指定扫描路径就开启,没有指定就不扫描,而这种方式必须要加个Import注解,最终使用注解实现)

具体使用的一些坑

ImportBeanDefinitionRegistrar

//该组件必须加在@Import中使用  直接注入容器registerBeanDefinitions方法不会被调用
public class ApiMapperScannerRegistrar implements ImportBeanDefinitionRegistrar {

    @Override
    public void registerBeanDefinitions(AnnotationMetadata metadata,BeanDefinitionRegistry registry) {
        AnnotationAttributes annoAttrs = AnnotationAttributes.fromMap(metadata
                .getAnnotationAttributes(ApiMapperScan.class.getName()));//获取@Import所标注的注解信息
        ApiMapperScanner scanner = new ApiMapperScanner(registry);
        // AnnotationAttributes有获取各种注解信息的方法
        scanner.doScan(annoAttrs.getStringArray("value"));
    }
    
}

注意若扫描空数组会报错

在这里插入图片描述

ClassPathBeanDefinitionScanner使用

public class ApiMapperScanner extends ClassPathBeanDefinitionScanner{

    public ApiMapperScanner(BeanDefinitionRegistry registry) {
        super(registry,false);//默认只扫描@Component与@ManagedBean建议取消默认的
        //重新添加过滤规则  类似注解组件扫描
        addIncludeFilter(new AnnotationTypeFilter(ApiMapper.class));
    }
    
    @Override
    protected Set<BeanDefinitionHolder> doScan(String... basePackages) {
        Set<BeanDefinitionHolder> definitionHolders = super.doScan(basePackages);
        handleBeanDefinitionHolder(definitionHolders);//对扫描结果进行拦截处理
        return definitionHolders;
    }
    
    private void handleBeanDefinitionHolder(Set<BeanDefinitionHolder> definitionHolders) {
        for (BeanDefinitionHolder holder:definitionHolders){
            BeanDefinition definition = holder.getBeanDefinition();
            //保留原来的接口
            String className = definition.getBeanClassName();
            //替换Bean的实现类
            definition.setBeanClassName("com.sk.api.mapper.factory.ApiMapperFactoryBean");
            MutablePropertyValues values = definition.getPropertyValues();
            //通过Bean的名字添加引用属性
            values.add("apiMapper",new RuntimeBeanReference("apiMapper"));
            //若类型不匹配Spring的类型转换器会生效
            values.add("targetClass",className);
            logger.info("ApiMapper Is Mapper:"+className);
        }
    }
    
    @Override//对扫描对象的条件限制
    protected boolean isCandidateComponent(AnnotatedBeanDefinition beanDefinition) {
        return beanDefinition.getMetadata().isInterface()&&beanDefinition.getMetadata().isIndependent();
    }
    
}

注解

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
// 一定要使用@Import导入
@Import(ApiMapperScannerRegistrar.class)
public @interface ApiMapperScan {

    String[] value();

}

使用效果

指定扫描路径
在这里插入图片描述
对路径下的接口自动代理
在这里插入图片描述
主要是对ApiMapper的封装使它支持类似MyBatis的包扫描功能
ApiMapper地址:https://blog.csdn.net/weixin_44598449/article/details/118658663
本项目完整地址:https://gitee.com/shaokang123/api-mapper-spring-boot-starter

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
BeanDefinitionRegistryPostProcessor 是 Spring Framework 中的一个接口,用于在应用程序上下文加载bean定义之前对BeanDefinition进行修改或自定义。它提供了一种扫描的方式来注册bean定义。 要实现BeanDefinitionRegistryPostProcessor 扫描,您可以使用ClassPathBeanDefinitionScanner 类来扫描指定的路径,并将扫描到的类注册为bean定义。 下面是一个示例代码: ```java import org.springframework.beans.factory.config.BeanDefinition; import org.springframework.beans.factory.support.BeanDefinitionRegistry; import org.springframework.beans.factory.support.BeanNameGenerator; import org.springframework.context.annotation.ClassPathBeanDefinitionScanner; import org.springframework.context.annotation.Configuration; import org.springframework.core.type.filter.AnnotationTypeFilter; @Configuration public class MyBeanDefinitionRegistryPostProcessor implements BeanDefinitionRegistryPostProcessor { private String basePackage = "com.example.package"; @Override public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) { // 创建一个 ClassPathBeanDefinitionScanner 对象 ClassPathBeanDefinitionScanner scanner = new ClassPathBeanDefinitionScanner(registry); // 设置自定义的 BeanNameGenerator scanner.setBeanNameGenerator(new MyBeanNameGenerator()); // 添加自定义的过滤器,这里使用了 AnnotationTypeFilter 作为示例 scanner.addIncludeFilter(new AnnotationTypeFilter(MyAnnotation.class)); // 扫描指定下的类,并将它们注册为bean定义 scanner.scan(basePackage); } @Override public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) { // 可以在这里进行一些其他的操作 } private class MyBeanNameGenerator implements BeanNameGenerator { // 自定义的 BeanNameGenerator 实现 } } ``` 在上面的示例中,我们实现了 BeanDefinitionRegistryPostProcessor 接口,并覆盖了 postProcessBeanDefinitionRegistry 方法。在该方法中,我们创建了一个 ClassPathBeanDefinitionScanner 对象,并设置了一些自定义的配置,例如路径、BeanNameGenerator 和过滤器。最后,我们调用 scanner 的 scan 方法来扫描指定下的类,并将它们注册为bean定义。 请注意,这只是一个示例代码,并不是完整的实现。在实际使用时,您可能需要根据自己的需求进行适当的修改和扩展。希望对您有所帮助!

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值