Mybatis之Mapper接口的实现原理

mybatis的mapper代理是用的jdk的动态代理,请看mybatis的如下代码:

/**
 *    Copyright 2009-2015 the original author or authors.
 *
 *    Licensed under the Apache License, Version 2.0 (the "License");
 *    you may not use this file except in compliance with the License.
 *    You may obtain a copy of the License at
 *
 *       http://www.apache.org/licenses/LICENSE-2.0
 *
 *    Unless required by applicable law or agreed to in writing, software
 *    distributed under the License is distributed on an "AS IS" BASIS,
 *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *    See the License for the specific language governing permissions and
 *    limitations under the License.
 */
package org.apache.ibatis.binding;

import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

import org.apache.ibatis.session.SqlSession;

/**
 * @author Lasse Voss
 */
public class MapperProxyFactory {

  private final Class mapperInterface;
  private final Map methodCache = new ConcurrentHashMap();

  public MapperProxyFactory(Class mapperInterface) {
    this.mapperInterface = mapperInterface;
  }

  public Class getMapperInterface() {
    return mapperInterface;
  }

  public Map getMethodCache() {
    return methodCache;
  }

  @SuppressWarnings("unchecked")
  protected T newInstance(MapperProxy mapperProxy) {
    //这里就是mybatis,创建mapper代理的关键代码,用的JDK的Proxy的方法
    return (T) Proxy.newProxyInstance(mapperInterface.getClassLoader(), new Class[] { mapperInterface }, mapperProxy);
  }

  public T newInstance(SqlSession sqlSession) {
    final MapperProxy mapperProxy = new MapperProxy(sqlSession, mapperInterface, methodCache);
    return newInstance(mapperProxy);
  }

}

下面我们来实现,用到的就是JDK的InvocationHandler接口和Proxy类

先写Mapper接口

public interface UserMapper {

	public void save(String name, int age);
}

然后实现InvocationHandler接口,复写invoke方法执行实际的代码

import second.UserMapper;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.Arrays;

/**
 * 只写接口,不用写实现类的动态代理,类似mybatis的mapper
 */
public class MapperProxy implements InvocationHandler{

	@Override
	public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {

		System.out.printf("class:%s, method:%s, args:%s, return:%s\n",
                proxy.getClass().getName(),
                method.getName(),
                Arrays.toString(args),
                method.getReturnType().getName());

		//TODO 在这里去动态实现代理类的行为
        if("save".equals(method.getName())){
            //TODO 执行sql的insert语句
        }
		return null;
	}
}

最后用Proxy的newInstance静态方法,实例化代理类

public static void main(String args[]){

		Class cla = UserMapper.class;
        UserMapper userProxy = (UserMapper)Proxy.newProxyInstance(cla.getClassLoader(), new Class[]{cla}, new MapperProxy());
        userProxy.save("tuyou", 25);
	}
到此实现完毕!

你可能感兴趣的:(java,mybatis,动态代理)