spring 整合mybatis 简单说明

spring整合mybatis简单说明

小小的疑问

有没有好奇,在使用spring 整合mybatis的时候,我们直接在service层注入mapper,mapper只是一个接口,但是就可以直接使用了。为什么可以直接用呢,spring是不能直接注入接口,带着这个疑问,我们往下面分析。

动态代理

我们知道,mybatis 其实是通过动态代理实现的,本文只是简单说明一下,myabtis的具体实现就不在阐述了。我们先看一下动态代理的内容。
先定义一个接口

public interface TestMapper {
     void testZ();
}

定义一个代理类

public class TestMapperProxy implements InvocationHandler {
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("proxy is "+proxy.getClass());
        System.out.println("method name is "+method.getName());
        return null;
    }
}

测试方法

   @Test
    public void test(){
       TestMapper testMapper=(TestMapper) Proxy.newProxyInstance(TestMapper.class.getClassLoader(),
               new Class[] { TestMapper.class },
                new TestMapperProxy());
       testMapper.testZ();
    }

输出结果为

proxy is class com.sun.proxy.$Proxy4
method name is testZ

通过以上代码,我们就可以用代理实现一个没有实现的接口的调用,spring 整合mybatis 其实也是这种方法,我们只要把这种代理对象放到spring容器中就行。那么,怎么放呢?

FactoryBean

我们知道spring有FactoryBean和BeanFactory,网上也有很多这2种比较的文章,我简单说一下把:

  • BeanFactory就是工厂模式,里面存储了我们的一些对象。
  • FactoryBean 就是一个bean,spring帮助可以构造对象,但是有时候我们需要重新定义这些对象的构造过程。

FactoryBean有2个重要的方法,一个是getObject(),另外一个是getObjectType()。

  • getObject() 这个方法会返回一个对象,这个对象会被spring管理。
  • getObjectType() 返回一个class类型,这个类型就是getObject()返回对象的class类型。
    接下来我们看下代码:
@Component
public class TestMapperFactoryBean implements FactoryBean {
    @Override
    public Object getObject() throws Exception {
        return Proxy.newProxyInstance(TestMapper.class.getClassLoader(),new Class[] { TestMapper.class },
                new TestMapperProxy());
    }

    @Override
    public Class<?> getObjectType() {
        return TestMapper.class;
    }
}

通过以上方法,我们就把类型为TestMapper的对象放到了spring容器中,我们就可以在别的类里面注入这个mapper了,是不是很简单。接下来看下整个的测试代码:

@RestController
@RequestMapping("/testProxy")
public class TestProxyController {
    @Autowired
    TestMapper testMapper;
    @RequestMapping("/testMapper")
    public String testMapper(){
        testMapper.testZ();
        return "OK";
    }
}

输出结果:

proxy is class com.sun.proxy.$Proxy78
method name is testZ

myabtis用的是MapperFactoryBean,ClassPathMapperScanner,大家有空可以去研究一下。
大功告成了,是不是很简单。
我们就是要用这个好奇心去看一些东西,学习一些东西,文章不足之处,希望大家多批评指正。

上一篇:Spring源码系列(五)——FactoryBean的使用与源码分析


下一篇:FactoryBean