People who have used MyBatis3 may wonder why the Mapper interface of MyBatis does not have an implementation class, but it can be used directly?
That's because MyBatis uses the interface implemented by Java dynamic proxy.
Here is just a simple example to illustrate the principle. It is not completely specific to MyBatis. We can also apply this idea to other places.
<span style="color: #0000ff">public</span> <span style="color: #0000ff">interface</span> MethodInterface { String helloWorld(); }
<span style="color: #0000ff">public</span> <span style="color: #0000ff">class</span> MethodProxy<T> <span style="color: #0000ff">implements</span><span style="color: #000000"> InvocationHandler { </span><span style="color: #0000ff">private</span> Class<T><span style="color: #000000"> methodInterface; </span><span style="color: #0000ff">public</span> MethodProxy(Class<T><span style="color: #000000"> methodInterface) { </span><span style="color: #0000ff">this</span>.methodInterface =<span style="color: #000000"> methodInterface; } @Override </span><span style="color: #0000ff">public</span> Object invoke(Object proxy, Method method, Object[] args) <span style="color: #0000ff">throws</span><span style="color: #000000"> Throwable { System.out.println(</span>"========================="<span style="color: #000000">); System.out.println(</span>"方法名:" +<span style="color: #000000"> method.getName()); </span><span style="color: #008000">//</span><span style="color: #008000">针对不同的方法进行不同的操作</span> <span style="color: #0000ff">return</span> <span style="color: #0000ff">null</span><span style="color: #000000">; } }</span>
Here we briefly talk about the implementation principle of MyBatis for the invoke
method. In this method, we can obtain the interface and method name through Method. The full name of the interface is equivalent to the namespace in MyBatis XML.
, the method name is equivalent to the id
in a specific method. That is to say, after passing the dynamic proxy, you can call the corresponding method through SqlSession
through namespace.id
. Using interfaces is more convenient, but in an indirect way.
<span style="color: #0000ff">public</span> <span style="color: #0000ff">class</span><span style="color: #000000"> MethodProxyFactory { </span><span style="color: #0000ff">public</span> <span style="color: #0000ff">static</span> <T> T newInstance(Class<T><span style="color: #000000"> methodInterface) { </span><span style="color: #0000ff">final</span> MethodProxy<T> methodProxy = <span style="color: #0000ff">new</span> MethodProxy<T><span style="color: #000000">(methodInterface); </span><span style="color: #0000ff">return</span><span style="color: #000000"> (T) Proxy.newProxyInstance( Thread.currentThread().getContextClassLoader(), </span><span style="color: #0000ff">new</span><span style="color: #000000"> Class[]{methodInterface}, methodProxy); } }</span>
This factory class can generate a dynamic proxy class for any interface.
MethodInterface method = MethodProxyFactory.newInstance(MethodInterface.<span style="color: #0000ff">class</span><span style="color: #000000">); method.helloWorld();</span>
Generally speaking, when it comes to dynamic agents, our usual usage is to deal with transactions, logs, or recording method execution efficiency. They are all special processing of pre- or post-implementation class methods.
Through this article, we can actually see another application direction, that is, there is no need to implement the class, and the interface method is executed directly through the dynamic proxy. MyBatis uses this method to facilitate us to call the method. Using this idea, we Maybe some better designs can be made in other aspects.
original:
The above is the detailed content of [Transfer] Simple implementation principle of MyBatis interface. For more information, please follow other related articles on the PHP Chinese website!