<?xml version="1.0" encoding="UTF-8"?> 
< projectxmlns = " http://maven.apache.org/POM/4.0.0" xmlns: xsi= " http://www.w3.org/2001/XMLSchema-instance" xsi: schemaLocation= " http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" > < modelVersion> </ modelVersion> < parent> < groupId> </ groupId> < artifactId> </ artifactId> < version> </ version> </ parent> < artifactId> </ artifactId> < properties> < maven.compiler.source> </ maven.compiler.source> < maven.compiler.target> </ maven.compiler.target> < project.build.sourceEncoding> </ project.build.sourceEncoding> </ properties> < dependencies> < dependency> < groupId> </ groupId> < artifactId> </ artifactId> < version> </ version> </ dependency> < dependency> < groupId> </ groupId> < artifactId> </ artifactId> < version> </ version> </ dependency> < dependency> < groupId> </ groupId> < artifactId> </ artifactId> < version> </ version> </ dependency> < dependency> < groupId> </ groupId> < artifactId> </ artifactId> < version> </ version> </ dependency> </ dependencies> </ project> CREATE  DATABASE  ` sun_mybatis` ; 
USE  ` sun_mybatis` ; 
CREATE  TABLE  ` monster` ( 
    ` id` INT           NOT  NULL  AUTO_INCREMENT , 
    ` age` INT           NOT  NULL , 
    ` birthday` DATE  DEFAULT  NULL , 
    ` email` VARCHAR ( 255 )  NOT  NULL , 
    ` gender` TINYINT       NOT  NULL , 
    ` name` VARCHAR ( 255 )  NOT  NULL , 
    ` salary` DOUBLE        NOT  NULL , 
    PRIMARY  KEY  ( ` id` ) 
)  CHARSET  =  utf8; 
INSERT  INTO  ` monster` ( ` age` ,  ` birthday` ,  ` email` ,  ` gender` ,  ` name` ,  ` salary` ) 
VALUES  ( 25 ,  '1998-01-15' ,  'example@example.com' ,  1 ,  'John Doe' ,  50000.00 ) ; 
 
 
<?xml version="1.0" encoding="utf-8" ?> 
< database> < propertyname = " driverClassName" value = " com.mysql.cj.jdbc.Driver" /> < propertyname = " url" value = " jdbc:mysql://bj--grp-.sql.tencentcdb.com:24169/sun_mybatis?useSSL=false& useUnicode=true& characterEncoding=UTF-8" /> < propertyname = " username" value = " " /> < propertyname = " password" value = " " /> </ database> package  com. sunxiansheng. mybatis. sqlsession ; 
import  org. dom4j.  Document ; 
import  org. dom4j.  DocumentException ; 
import  org. dom4j.  Element ; 
import  org. dom4j. io.  SAXReader ; 
import  org. slf4j.  Logger ; 
import  org. slf4j.  LoggerFactory ; 
import  java. io.  InputStream ; 
import  java. sql.  Connection ; 
import  java. sql.  DriverManager ; 
import  java. sql.  SQLException ; 
import  java. util.  List ; 
public  class  SunConfiguration  { 
    private  static  final  Logger  log =  LoggerFactory . getLogger ( SunConfiguration . class ) ; 
    private  static  ClassLoader  loader =  ClassLoader . getSystemClassLoader ( ) ; 
    
    public  Connection  build ( String  resource)  { 
        InputStream  resourceAsStream =  loader. getResourceAsStream ( resource) ; 
        
        SAXReader  saxReader =  new  SAXReader ( ) ; 
        try  { 
            
            Document  document =  saxReader. read ( resourceAsStream) ; 
            
            Element  rootElement =  document. getRootElement ( ) ; 
            
            List < Element > =  rootElement. elements ( "property" ) ; 
            
            String  driverClassName =  null ; 
            String  url =  null ; 
            String  username =  null ; 
            String  password =  null ; 
            
            for  ( Element  element :  property)  { 
                String  name =  element. attributeValue ( "name" ) ; 
                String  value =  element. attributeValue ( "value" ) ; 
                switch  ( name)  { 
                    case  "driverClassName" : 
                        driverClassName =  value; 
                        log. info ( "加载驱动类:{}" ,  value) ; 
                        break ; 
                    case  "url" : 
                        url =  value; 
                        log. info ( "加载url:{}" ,  value) ; 
                        break ; 
                    case  "username" : 
                        username =  value; 
                        log. info ( "加载用户名:{}" ,  value) ; 
                        break ; 
                    case  "password" : 
                        password =  value; 
                        log. info ( "加载密码:{}" ,  value) ; 
                        break ; 
                    default : 
                        throw  new  RuntimeException ( "未知的property属性名" ) ; 
                } 
            } 
            
            Class . forName ( driverClassName) ; 
            return  DriverManager . getConnection ( url,  username,  password) ; 
        }  catch  ( DocumentException  |  ClassNotFoundException  |  SQLException  e)  { 
            log. error ( "解析xml配置文件失败" ,  e) ; 
            throw  new  RuntimeException ( e) ; 
        } 
    } 
} 
package  com. sunxiansheng. mybatis. sqlsession ; 
import  org. junit.  Test ; 
import  java. sql.  Connection ; 
public  class  SunConfigurationTest  { 
    @Test 
    public  void  build ( )  { 
        SunConfiguration  sunConfiguration =  new  SunConfiguration ( ) ; 
        Connection  build =  sunConfiguration. build ( "sun-config.xml" ) ; 
        System . out. println ( "build = "  +  build) ; 
    } 
} 
 
package  com. sunxiansheng. mybatis. entity ; 
import  lombok.  Data ; 
import  java. io.  Serializable ; 
import  java. util.  Date ; 
@Data 
public  class  Monster  implements  Serializable  { 
    private  Integer  id; 
    private  Integer  age; 
    private  Date  birthday; 
    private  String  email; 
    private  Byte  gender; 
    private  String  name; 
    private  Double  salary; 
    private  static  final  long  serialVersionUID =  1L ; 
} 
package  com. sunxiansheng. mybatis. sqlsession ; 
public  interface  Executor  { 
    public  < T > T  query ( String  sql,  Object  parameter) ; 
} 
package  com. sunxiansheng. mybatis. sqlsession ; 
import  com. sunxiansheng. mybatis. entity.  Monster ; 
import  org. slf4j.  Logger ; 
import  org. slf4j.  LoggerFactory ; 
import  java. sql.  Connection ; 
import  java. sql.  PreparedStatement ; 
import  java. sql.  ResultSet ; 
public  class  SunExecutor  implements  Executor { 
    public  static  final  SunConfiguration  configuration =  new  SunConfiguration ( ) ; 
    private  static  final  Logger  log =  LoggerFactory . getLogger ( SunExecutor . class ) ; 
    @Override 
    public  < T > T  query ( String  sql,  Object  parameter)  { 
        
        Connection  connection =  configuration. build ( "sun-config.xml" ) ; 
        log. info ( "获取连接:{}" ,  connection) ; 
        ResultSet  resultSet =  null ; 
        PreparedStatement  preparedStatement =  null ; 
        
        Monster  monster =  new  Monster ( ) ; 
        try  { 
            
            preparedStatement =  connection. prepareStatement ( sql) ; 
            
            preparedStatement. setString ( 1 ,  parameter. toString ( ) ) ; 
            
            resultSet =  preparedStatement. executeQuery ( ) ; 
            
            while  ( resultSet. next ( ) )  { 
                monster. setId ( resultSet. getInt ( "id" ) ) ; 
                monster. setAge ( resultSet. getInt ( "age" ) ) ; 
                monster. setBirthday ( resultSet. getDate ( "birthday" ) ) ; 
                monster. setEmail ( resultSet. getString ( "email" ) ) ; 
                monster. setGender ( resultSet. getByte ( "gender" ) ) ; 
                monster. setName ( resultSet. getString ( "name" ) ) ; 
                monster. setSalary ( resultSet. getDouble ( "salary" ) ) ; 
            } 
            log. info ( "查询结果:{}" ,  monster) ; 
        }  catch  ( Exception  e)  { 
            throw  new  RuntimeException ( e) ; 
        }  finally  { 
            
            try  { 
                if  ( resultSet !=  null )  { 
                    resultSet. close ( ) ; 
                } 
                if  ( preparedStatement !=  null )  { 
                    preparedStatement. close ( ) ; 
                } 
                if  ( connection !=  null )  { 
                    connection. close ( ) ; 
                } 
            }  catch  ( Exception  e)  { 
                throw  new  RuntimeException ( e) ; 
            } 
        } 
        
        return  ( T )  monster; 
    } 
} 
@Test 
public  void  executor ( )  { 
    SunExecutor  sunExecutor =  new  SunExecutor ( ) ; 
    
    Monster  monster =  sunExecutor. query ( "select * from monster where id = ?" ,  1 ) ; 
} 
 
package  com. sunxiansheng. mybatis. sqlsession ; 
public  class  SunSqlSession  { 
    
    private  Executor  executor =  new  SunExecutor ( ) ; 
    
    private  SunConfiguration  configuration =  new  SunConfiguration ( ) ; 
    public  < T > T  selectOne ( String  statement,  Object  parameter)  { 
        return  executor. query ( statement,  parameter) ; 
    } 
} 
@Test 
public  void  selectOne ( )  { 
    SunSqlSession  sunSqlSession =  new  SunSqlSession ( ) ; 
    Monster  monster =  sunSqlSession. selectOne ( "select * from monster where id = ?" ,  1 ) ; 
    System . out. println ( "monster = "  +  monster) ; 
} 
 
package  com. sunxiansheng. mapper ; 
import  com. sunxiansheng. entity.  Monster ; 
public  interface  MonsterMapper  { 
    public  Monster  getMonsterById ( Integer  id) ; 
} 
<?xml version="1.0" encoding="UTF-8" ?> 
< mappernamespace = " com.sunxiansheng.mapper.MonsterMapper" > < selectid = " getMonsterById" resultType = " com.sunxiansheng.entity.Monster" > </ select> </ mapper> package  com. sunxiansheng. mybatis. config ; 
import  lombok.  Data ; 
@Data 
public  class  Function  { 
    
    private  String  sqlType; 
    
    private  String  funcName; 
    
    private  String  sql; 
    
    private  Object  resultType; 
} 
package  com. sunxiansheng. mybatis. config ; 
import  java. util.  List ; 
public  class  MapperBean  { 
    
    private  String  interfaceName; 
    
    private  List < Function > ; 
} 
 
 
 
public  MapperBean  readMapper ( String  path)  { 
    
    MapperBean  mapperBean =  new  MapperBean ( ) ; 
    
    ClassLoader  loader =  ClassLoader . getSystemClassLoader ( ) ; 
    InputStream  resourceAsStream =  loader. getResourceAsStream ( path) ; 
    
    SAXReader  saxReader =  new  SAXReader ( ) ; 
    try  { 
        
        Document  document =  saxReader. read ( resourceAsStream) ; 
        
        Element  rootElement =  document. getRootElement ( ) ; 
        
        String  namespace =  rootElement. attributeValue ( "namespace" ) ; 
        
        List < Element > =  rootElement. elements ( ) ; 
        
        List < Function > =  elements. stream ( ) . map ( 
                element ->  { 
                    Function  function =  new  Function ( ) ; 
                    
                    String  sqlType =  element. getName ( ) ; 
                    
                    String  funcName =  element. attributeValue ( "id" ) ; 
                    
                    String  resultType =  element. attributeValue ( "resultType" ) ; 
                    
                    String  sql =  element. getTextTrim ( ) ; 
                    
                    function. setSqlType ( sqlType) 
                            . setFuncName ( funcName) 
                            . setResultType ( resultType) 
                            . setSql ( sql) ; 
                    return  function; 
                } 
        ) . collect ( Collectors . toList ( ) ) ; 
        
        mapperBean. setInterfaceName ( namespace) ; 
        mapperBean. setFunctions ( functions) ; 
    }  catch  ( DocumentException  e)  { 
        throw  new  RuntimeException ( e) ; 
    } 
    
    log. info ( "mapperBean:{}" ,  mapperBean) ; 
    return  mapperBean; 
} 
    @Test 
    public  void  readMapper ( )  { 
        SunConfiguration  sunConfiguration =  new  SunConfiguration ( ) ; 
        sunConfiguration. readMapper ( "MonsterMapper.xml" ) ; 
    } 
 
 
package  com. sunxiansheng. mybatis. sqlsession ; 
import  java. lang. reflect.  Proxy ; 
public  class  MapperProxyFactory  { 
    public  static  < T > T  getMapperProxy ( Class < T > ,  SunSqlSession  sunSqlSession,  SunConfiguration  sunConfiguration)  { 
        return  ( T )  Proxy . newProxyInstance ( clazz. getClassLoader ( ) ,  new  Class [ ] { clazz} ,  new  SunMapperProxy ( sunSqlSession,  clazz,  sunConfiguration) ) ; 
    } 
} 
package  com. sunxiansheng. mybatis. sqlsession ; 
import  com. sunxiansheng. mybatis. config.  Function ; 
import  com. sunxiansheng. mybatis. config.  MapperBean ; 
import  org. slf4j.  Logger ; 
import  org. slf4j.  LoggerFactory ; 
import  java. lang. reflect.  InvocationHandler ; 
import  java. lang. reflect.  Method ; 
import  java. util.  List ; 
public  class  SunMapperProxy  implements  InvocationHandler  { 
    private  static  final  Logger  log =  LoggerFactory . getLogger ( SunMapperProxy . class ) ; 
    
    private  SunSqlSession  sunSqlSession; 
    
    private  String  mapperFile; 
    
    private  SunConfiguration  sunConfiguration; 
    public  SunMapperProxy ( SunSqlSession  sunSqlSession,  Class < ? > ,  SunConfiguration  sunConfiguration)  { 
        this . sunSqlSession =  sunSqlSession; 
        this . mapperFile =  mapperFile. getSimpleName ( )  +  ".xml" ; 
        this . sunConfiguration =  sunConfiguration; 
    } 
    @Override 
    public  Object  invoke ( Object  proxy,  Method  method,  Object [ ]  args)  throws  Throwable  { 
        
        String  methodName =  method. getName ( ) ; 
        
        MapperBean  readMapper =  sunConfiguration. readMapper ( mapperFile) ; 
        
        List < Function > =  readMapper. getFunctions ( ) ; 
        Function  targetFunction =  null ; 
        for  ( Function  function :  functions)  { 
            if  ( methodName. equals ( function. getFuncName ( ) ) )  { 
                targetFunction =  function; 
                break ; 
            } 
        } 
        
        String  sqlType =  targetFunction. getSqlType ( ) ; 
        String  sql =  targetFunction. getSql ( ) ; 
        
        
        if  ( sqlType. equals ( "select" ) )  { 
            Object  selected =  sunSqlSession. selectOne ( sql,  args[ 0 ] ) ; 
            log. info ( "invoke查询结果:{}" ,  selected) ; 
            return  selected; 
        } 
        return  null ; 
    } 
} 
@Test 
public  void  getResult ( )  { 
    MonsterMapper  mapperProxy =  MapperProxyFactory . getMapperProxy ( MonsterMapper . class ,  new  SunSqlSession ( ) ,  new  SunConfiguration ( ) ) ; 
    Monster  monsterById =  mapperProxy. getMonsterById ( 1 ) ; 
}