自学内容网 自学内容网

理解mybatis 里的mapper 实现原理

目的

主要想搞明白,mybatis 是如何通过只通过声明一个mapper 接口,就能实现crud 操作了

实现注解

@Retention(RetentionPolicy.RUNTIME)
public @interface Mapper {
}

@Retention(RetentionPolicy.RUNTIME)
public @interface Insert {
    String value();
}

代理

public class MapperProxy implements InvocationHandler {

    public MapperProxy() throws Exception {
        // 创建数据库连接(此处使用示例数据库信息)
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        // 这里可以拦截不同的方法来实现不同的crud操作
        if (method.isAnnotationPresent(Insert.class)) {
            // 获取注解中的 SQL
            Insert insert = method.getAnnotation(Insert.class);
            String sql = insert.value();

            // 从参数中获取 User 对象,这里可以执行SQL
            User user = (User) args[0];
            sql = sql.replace("#{name}", "'" + user.getName() + "'");


            System.out.println(sql);
        }
        return null;
    }
}

public class MapperProxyFactory<T> implements FactoryBean<T> {
    private Class<T> mapperInterface;

    public MapperProxyFactory(Class<T> mapperInterface) {
        this.mapperInterface = mapperInterface;
    }
    
    @Override
    public T getObject() throws Exception {
        MapperProxy proxy = new MapperProxy();
        //生成代理类
        return (T) Proxy.newProxyInstance(mapperInterface.getClassLoader(),
                new Class<?>[]{mapperInterface},
                proxy);
    }

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

  
}

声明mapper

@Mapper
public interface UserMapper {
    @Insert("INSERT INTO User (name) VALUES (#{name})")
    void insertUser(User user);
}

扫描类

public class MapperScannerConfigurer implements BeanDefinitionRegistryPostProcessor {
    private String basePackage;

    public void setBasePackage(String basePackage) {
        this.basePackage = basePackage;
    }

    @Override
    public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
        // 扫描包路径下的 Mapper 接口,注册到容器
        ClassPathScanningCandidateComponentProvider scanner = new ClassPathScanningCandidateComponentProvider(false) {
            @Override
            protected boolean isCandidateComponent(AnnotatedBeanDefinition metadataReader)  {
                return true;
            }
        };
        scanner.addIncludeFilter(new AnnotationTypeFilter(Mapper.class));
        for (BeanDefinition beanDefinition : scanner.findCandidateComponents(basePackage)) {
            GenericBeanDefinition definition = (GenericBeanDefinition) beanDefinition;
            String beanClassName = definition.getBeanClassName();

            // 设置为 MapperFactoryBean 代理类
            definition.getConstructorArgumentValues().addGenericArgumentValue(beanClassName);
            definition.setBeanClass(MapperProxyFactory.class);

            // 注册 Bean 到 Spring 容器
            registry.registerBeanDefinition(beanClassName, definition);
        }
    }

    @Override
    public void postProcessBeanFactory(org.springframework.beans.factory.config.ConfigurableListableBeanFactory beanFactory) throws BeansException {
        // 不需要实现这个方法
    }
}


启动类

@Configuration
public class AppConfig {

    @Bean
    public MapperScannerConfigurer mapperScannerConfigurer() {
        MapperScannerConfigurer configurer = new MapperScannerConfigurer();
        configurer.setBasePackage("com.demo.ma.mapper"); // 设置扫描包路径
        return configurer;
    }
}

public class Application {
    public static void main(String[] args) {
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
        UserMapper userMapper = context.getBean(UserMapper.class);
        // 测试调用
        userMapper.insertUser(new User(1,"aa"));
        context.close();
    }
}

public class User {
    private Integer id;
    private String name;

    public User(Integer id, String name) {
        this.id = id;
        this.name = name;
    }

    // Getters and Setters
    public Integer getId() {
        return id;
    }
    public void setId(Integer id) {
        this.id = id;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
}

原文地址:https://blog.csdn.net/qq_22222499/article/details/143824858

免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!