Spring整合MyBatis

73 阅读1分钟

Spring整合MyBatis

MyBatis通过generatorConfig.xml生成的XXXMapper接口,MyBatis会生成接口对应的bean,放到Spring容器中管理;MyBatis是生成一个代理对象,使用到了FactoryBean,放到了Spring容器中,容器中的bean可以注入到其他组件中

生成代理对象并将bean交给FactoryBean的过程: 1、直接将一个对象放到Spring容器中:beanFactory.registerSingleton("xxx", new Xxx()); 2、通过FactoryBean生成一个代理对象,context加载时XXXFactoryBean实际会生成一个代理对象 beanClass是:com.pl.processor.TestFactoryBean,实际生成的是XXXMapper的代理对象,调用代理对象的任何方法时都会执行一遍invoke()方法

@Component
public class TestFactoryBean implements FactoryBean {
​
    private Class mapper;
​
    public TestFactoryBean(Class input) {
        this.mapper = input;
    }
​
    // OrderMapper ------->new TestFactoryBean(OrderMapper.class)------>OrderMapper的代理对象
    // bean的name是testFactoryBean,生成的对象是代理对象UserMapper
    @Override
    public Object getObject() throws Exception {
        Object o = Proxy.newProxyInstance(mapper.getClassLoader(), new Class[]{mapper}, new InvocationHandler() {
            // 调用代理对象的方法时都会调用invoke
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                System.out.println(method.getName());
                return null;
            }
        });
        return o;
    }
​
    @Override
    public Class<?> getObjectType() {
        return mapper;
    }
​
    // 可以不实现,default方法,默认返回true
    @Override
    public boolean isSingleton() {
        return true;
    }
}

3、依赖FactoryBean,在生成Bean的前置阶段:Class解析BeanDefinition的时候,批量的生成多个代理类; 解决方案: ① 自定义BeanDefinitionRegister实现ImportBeanDefinitionRegistrar,在registerBeanDefinitions方法中注册新的BeanDefinition ② 将修改后的BeanDefinition然后导入到BeanFactory中的BeanDefinitionMap: ③ 将该动作引入到Bean初始化的方式: @Import(TestBeanDefinitionRegister.class)

public class TestBeanDefinitionRegister implements ImportBeanDefinitionRegistrar {
    @Override
    public void registerBeanDefinitions(AnnotationMetadata annotationMetadata, BeanDefinitionRegistry beanDefinitionRegistry) {
        // ① beanDefinitionRegistry注册表
        List<Class> mappers = new ArrayList<Class>();
        mappers.add(UserMapper.class);
        mappers.add(OrderMapper.class);
        
        // ② 优化方式:新增一个Mapper之后如何处理?如何实现自动导入
        
        
        for (Class mapper : mappers) {
            BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition();
            AbstractBeanDefinition beanDefinition = builder.getBeanDefinition();
​
            // 设置BeanDefinition对应的beanClass,改Class专门用来生产代理对象
            beanDefinition.setBeanClass(TestFactoryBean.class);
            beanDefinition.getConstructorArgumentValues().addGenericArgumentValue(mapper);
            beanDefinitionRegistry.registerBeanDefinition(mapper.getSimpleName(), beanDefinition);
        }
    }
}