ImportBeanDefinitionRegistrar解析

ImportBeanDefinitionRegistrar是spring提供的一个扩展点,和ImportSelector不同的是,ImportBeanDefinitionRegistrar提供了一个注册器registry,用于注册BeanDefinition。此外,ImportBeanDefinitionRegistrar还可以参与BeanDefinition的创建过程。

Mybatis的@MapperScan扫描指定包下的接口(这些接口并没有实现类),进而完成数据库操作。底层正是基于动态代理和ImportBeanDefinitionRegistrar实现的。

下面自己来模拟实现一个吧:

public interface Mapper {
    @MySelect("select * from user")
    String query();
}
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface MySelect {
    String value();
}
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@Import(MyBeanDefinitionRegistrar.class)
public @interface MyMapperScan {
    String value();
}
public class MyBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar,ResourceLoaderAware {

    ResourceLoader resourceLoader;
    @Override
    public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
        try {
            //获取@MyMapperScan包路径,并扫描
            Map<String, Object> attributes = importingClassMetadata.getAnnotationAttributes(MyMapperScan.class.getName());
            AnnotationAttributes annotationAttributes = AnnotationAttributes.fromMap(attributes);
            String packageName = annotationAttributes.getString("value");
            String packageFileName=packageName.replace(".","/");
            File[] files = resourceLoader.getResource(packageFileName).getFile().listFiles();
            for (File file : files) {
                System.out.println(file);
                String fileName = file.getName().replace(".class", "");
                Class<?> aClass = Class.forName(packageName+"."+fileName);
                if(aClass.isInterface()&&!aClass.isAnnotation()){
                    BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition();
                    GenericBeanDefinition beanDefinition = (GenericBeanDefinition) builder.getBeanDefinition();
                    beanDefinition.getConstructorArgumentValues().addGenericArgumentValue(packageName+"."+fileName);
                    beanDefinition.setBeanClass(MyFactoryBean.class);
                    registry.registerBeanDefinition(fileName,beanDefinition);
                }
            }
        }catch (Exception e){
            e.printStackTrace();
        }
    }

    @Override
    public void setResourceLoader(ResourceLoader resourceLoader) {
        this.resourceLoader = resourceLoader;
    }
}
public class MyFactoryBean implements FactoryBean,InvocationHandler {
    //要代理的对象
    Class clazz;

    public MyFactoryBean(Class clazz) {
        this.clazz = clazz;
    }

    @Override
    public Object getObject() throws Exception {
        Object proxy = Proxy.newProxyInstance(this.getClass().getClassLoader(), new Class[]{clazz}, this);
        return proxy;
    }

    @Override
    public Class<?> getObjectType() {
        return clazz;
    }

    @Override
    public boolean isSingleton() {
        return false;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        //获取方法上的@MySelect
        MySelect mySelect = method.getAnnotation(MySelect.class);
        String value = mySelect.value();
        System.out.println(value);
        return null;
    }
}
@Configuration
@MyMapperScan("com.su.spring.importBeanDefinitionRegistrar")
public class AppConfig {
}
public class Test {
    public static void main(String[] args) {
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
        Mapper mapper = (Mapper) context.getBean("Mapper");
        mapper.query();
    }
}

在这里插入图片描述
这时候,我们已经拿到了sql,接下来就不进行jdbc操作了。

关于ImportBeanDefinitionRegistrar在spring当中什么时候解析处理的,见Spring-IoC之BeanFactory(Annotation)

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值