Brief description of spring integrating mybatis

A little question

Are you curious? When using spring to integrate mybatis, we directly inject mapper into the service layer. Mapper is just an interface, but it can be used directly. Why can it be used directly? Spring cannot be directly injected into the interface. With this question, let's analyze it below.

Dynamic agent

As we know, mybatis is actually implemented through dynamic agent. This article is just a brief description, and the specific implementation of myabtis is not described. Let's take a look at the content of dynamic proxy first.
Define an interface first

public interface TestMapper {
     void testZ();
}

Define a proxy class

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 method

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

The output result is

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

Through the above code, we can use a proxy to call an interface that is not implemented. Spring integration mybatis is actually the same method. We just need to put this proxy object into the spring container. So, how?

FactoryBean

We know that spring has FactoryBean and BeanFactory, and there are many articles comparing the two on the Internet. Let me briefly say:

  • BeanFactory is the factory pattern, which stores some of our objects.
  • FactoryBean is a bean. spring helps to construct objects, but sometimes we need to redefine the construction process of these objects.

FactoryBean has two important methods: getObject() and getObjectType().

  • The getObject() method will return an object, which will be managed by spring.
  • getObjectType() returns a class type, which is the class type of the object returned by getObject().
    Next, let's look at the code:
@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;
    }
}

Through the above methods, we put the object of type TestMapper into the spring container, and we can inject this mapper into other classes. Isn't it very simple. Next, let's look at the whole test code:

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

Output results:

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

myabtis uses MapperFactoryBean and ClassPathMapperScanner. You can study it when you are free.
It's done. Isn't it easy.
We just want to use this curiosity to see and learn something. I hope you can criticize and correct the shortcomings of the article.

Added by dscuber9000 on Mon, 03 Jan 2022 05:47:01 +0200