Spring整合Mybatis原理实现

1、使用动态代理实现扫描的接口

public class MapperFactoryBean implements FactoryBean {

    private Class mapper;

    /**
     * 构造传入mapper类型
     * @param mapper
     */
    public MapperFactoryBean(Class mapper){
        this.mapper = mapper;
    }

    @Override
    public Object getObject() throws Exception {
        //创建mapper代理对象
        return Proxy.newProxyInstance(MapperFactoryBean.class.getClassLoader(), new Class[]{mapper}, new InvocationHandler() {
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                if(Object.class.equals(method.getDeclaringClass())){
                    //如果为顶级Object的方法直接跳过
                    return method.invoke(this,args);
                }else {
                    //执行处理SQL,JDBC调用逻辑
                    System.out.println("执行SQL");
                }
                return null;
            }
        });
    }

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

2、创建Mybatis的Mapper扫描注解

@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE})
@Documented
@Import(MapperImportBeanDefinitionRegistrar.class)
public @interface EnableMapperScan {
    String value();//单个包路径
    String[] packages() default {};//扫描包的路径
}

3、核心注册代理类

public class MapperImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar, ResourceLoaderAware, EnvironmentAware, Ordered {

    private Environment environment;

    private ResourceLoader resourceLoader;

    private String[] packages;

    private String resourcePattern = DEFAULT_RESOURCE_PATTERN;

    static final String DEFAULT_RESOURCE_PATTERN = "**/*.class";

    private ResourcePatternResolver resourcePatternResolver;

    private MetadataReaderFactory metadataReaderFactory;

    @Override
    public void setEnvironment(Environment environment) {
        this.environment = environment;

    }

    @Override
    public void setResourceLoader(ResourceLoader resourceLoader) {
        this.resourceLoader = resourceLoader;
    }

    @Override
    public int getOrder() {
        return 0;
    }

    @Override
    public void registerBeanDefinitions(AnnotationMetadata annotationMetadata, BeanDefinitionRegistry beanDefinitionRegistry) {
        //定义BeanDefinition并设置构造参数
        BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition();
        AbstractBeanDefinition beanDefinition = builder.getBeanDefinition();
        beanDefinition.setBeanClass(MapperFactoryBean.class);
        Map<String, Object> defaultAttrs = annotationMetadata.getAnnotationAttributes(EnableMapperScan.class.getName(), true);
        String[] value = (String[]) defaultAttrs.get("value");
        if(ArrayUtils.isNotEmpty(value)){
            this.packages = value;
        }else {
            String[] basePackages = (String[]) defaultAttrs.get("packages");
            if(ArrayUtils.isNotEmpty(basePackages)){
                this.packages = basePackages;
            }
        }
        //创建类路径包扫描
        for (String aPackage : packages) {
            String packageSearchPath = ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX +
                    resolveBasePackage(aPackage) + '/' + this.resourcePattern;
            try {
                Resource[] resources = getResourcePatternResolver().getResources(packageSearchPath);
                for (Resource resource : resources) {
                    if(resource.isReadable()){
                        MetadataReader metadataReader = getMetadataReaderFactory().getMetadataReader(resource);
                        String className = metadataReader.getClassMetadata().getClassName();
                        Class<?> aClass = Class.forName(className);
                        beanDefinition.getConstructorArgumentValues().addGenericArgumentValue(aClass);
                        beanDefinitionRegistry.registerBeanDefinition(className,beanDefinition);
                    }
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    public final MetadataReaderFactory getMetadataReaderFactory() {
        if (this.metadataReaderFactory == null) {
            this.metadataReaderFactory = new CachingMetadataReaderFactory();
        }
        return this.metadataReaderFactory;
    }

    protected String resolveBasePackage(String basePackage) {
        return ClassUtils.convertClassNameToResourcePath(this.environment.resolveRequiredPlaceholders(basePackage));
    }

    private ResourcePatternResolver getResourcePatternResolver() {
        return this.resourcePatternResolver = ResourcePatternUtils.getResourcePatternResolver(resourceLoader);
    }
}

4、启动类加上启用注解

@SpringBootApplication
@EnableMapperScan("com.liangjiachu.liangjiachuframework.mybatis.mapper")
public class LiangjiachuFrameworkApplication {

    public static void main(String[] args) {
        ConfigurableApplicationContext applicationContext = SpringApplication.run(LiangjiachuFrameworkApplication.class, args);
        UserMapper userMapper = applicationContext.getBean(UserMapper.class);
        userMapper.getUserInfo();
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值