Skip to content

Commit 920849a

Browse files
author
chengpengxiang
committed
自己写一个mybatis框架
1 parent f91fd4b commit 920849a

20 files changed

Lines changed: 411 additions & 4 deletions

File tree

02nio/nio02/pom.xml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,12 @@
2525
</properties>
2626

2727
<dependencies>
28+
<!-- https://mvnrepository.com/artifact/org.mybatis/mybatis -->
29+
<dependency>
30+
<groupId>org.mybatis</groupId>
31+
<artifactId>mybatis</artifactId>
32+
<version>3.5.10</version>
33+
</dependency>
2834

2935
<dependency>
3036
<groupId>io.netty</groupId>

02nio/nio02/src/main/java/io/github/kimmking/gateway/NettyServerApplication.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ public static void main(String[] args) {
2222

2323

2424
// 这是多个后端url走随机路由的例子
25-
String proxyServers = System.getProperty("proxyServers","http://localhost:8801,http://localhost:8802");
25+
String proxyServers = System.getProperty("proxyServers","http://localhost:8801,http://localhost:8801");
2626
int port = Integer.parseInt(proxyPort);
2727
System.out.println(GATEWAY_NAME + " " + GATEWAY_VERSION +" starting...");
2828
HttpInboundServer server = new HttpInboundServer(port, Arrays.asList(proxyServers.split(",")));

04fx/spring01/src/main/java/io/kimmking/homework/aop/TestDemo.java

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
package io.kimmking.homework.aop;
22

3+
import io.kimmking.homework.mybatis.IUserDao;
4+
import org.springframework.beans.factory.BeanFactory;
5+
import org.springframework.context.support.ClassPathXmlApplicationContext;
6+
37
import java.lang.reflect.Proxy;
48

59
/**
@@ -12,5 +16,10 @@ public static void main(String[] args) {
1216
SchoolProxy schoolProxy = new SchoolProxy(new ISchool());
1317
School school = (School) Proxy.newProxyInstance(schoolProxy.getClass().getClassLoader(), new Class[]{School.class},schoolProxy);
1418
school.start();
19+
System.out.println("===============");
20+
System.out.println("测试mybatis");
21+
BeanFactory beanFactory = new ClassPathXmlApplicationContext("classpath:/applicationContextcpx.xml");
22+
IUserDao userDao = beanFactory.getBean("userDao", IUserDao.class);
23+
System.out.println(userDao.queryUserInfo());
1524
}
1625
}
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
package io.kimmking.homework.mockmybatis;
2+
3+
import io.kimmking.homework.mockmybatis.session.SqlSession;
4+
5+
import java.io.Serializable;
6+
import java.lang.reflect.InvocationHandler;
7+
import java.lang.reflect.Method;
8+
import java.util.Map;
9+
10+
/**
11+
* @ClassName MapperProxy
12+
* @Author jackchen
13+
* @Date 2022/8/2 17:39
14+
* @Description TODO
15+
**/
16+
public class MapperProxy<T> implements InvocationHandler, Serializable {
17+
private static final long serialVersionUID = -6424540398559729838L;
18+
private SqlSession sqlSession;
19+
private final Class<T> mappperInterface;
20+
21+
public MapperProxy(SqlSession sqlSession, Class<T> mappperInterface) {
22+
this.sqlSession = sqlSession;
23+
this.mappperInterface = mappperInterface;
24+
}
25+
26+
@Override
27+
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
28+
if (Object.class.equals(method.getDeclaringClass())) {
29+
return method.invoke(this, args);
30+
}
31+
System.out.println(mappperInterface.getName());
32+
return "你被代理了" + sqlSession.selectOne(method.getName(), args);
33+
}
34+
}
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
package io.kimmking.homework.mockmybatis;
2+
3+
import io.kimmking.homework.mockmybatis.session.SqlSession;
4+
5+
import java.lang.reflect.Proxy;
6+
import java.util.Map;
7+
8+
/**
9+
* @ClassName MapperProxyFactory
10+
* @Author jackchen
11+
* @Date 2022/8/2 17:43
12+
* @Description TODO
13+
**/
14+
public class MapperProxyFactory<T> {
15+
private final Class<T> mapperInterface;
16+
17+
public MapperProxyFactory(Class<T> mapperInterface) {
18+
this.mapperInterface = mapperInterface;
19+
}
20+
21+
public T newInstance(SqlSession sqlSession) {
22+
final MapperProxy<T> mapperProxy = new MapperProxy<>(sqlSession, mapperInterface);
23+
return (T) Proxy.newProxyInstance(mapperProxy.getClass().getClassLoader(), new Class[]{mapperInterface}, mapperProxy);
24+
}
25+
}
Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
package io.kimmking.homework.mockmybatis.binding;
2+
3+
import io.kimmking.homework.mockmybatis.MapperProxyFactory;
4+
import io.kimmking.homework.mockmybatis.session.SqlSession;
5+
import io.kimmking.homework.mockmybatis.utils.ClassScanner;
6+
7+
import java.io.File;
8+
import java.io.IOException;
9+
import java.util.ArrayList;
10+
import java.util.HashMap;
11+
import java.util.HashSet;
12+
import java.util.List;
13+
import java.util.Map;
14+
import java.util.Set;
15+
16+
/**
17+
* @ClassName MapperRegistry
18+
* @Author jackchen
19+
* @Date 2022/8/2 18:03
20+
* @Description TODO
21+
**/
22+
public class MapperRegistry {
23+
/**
24+
* 将mapper接口和mapper接口的代理工程联系起来
25+
*/
26+
private final Map<Class<?>, MapperProxyFactory<?>> knownMappers = new HashMap<>();
27+
28+
public <T> T getMapper(Class<T> type, SqlSession sqlSession) {
29+
final MapperProxyFactory<T> mapperProxyFactory = (MapperProxyFactory<T>) knownMappers.get(type);
30+
if (mapperProxyFactory == null) {
31+
throw new RuntimeException("mapper接口对应的代理工厂没有找见");
32+
}
33+
try {
34+
return mapperProxyFactory.newInstance(sqlSession);
35+
} catch (Exception e) {
36+
throw new RuntimeException("不能获取mapper接口的实例对象");
37+
}
38+
}
39+
40+
//将mapper接口注册到knowMapper里面去
41+
public <T> void addMapper(Class<T> type) {
42+
if (type.isInterface()) {
43+
if (knownMappers.containsKey(type)) {
44+
throw new RuntimeException("mapper接口已经被注册了");
45+
}
46+
knownMappers.put(type, new MapperProxyFactory<>(type));
47+
}
48+
}
49+
50+
public void addMappers(String packageName) throws IOException, ClassNotFoundException {
51+
List<Class> mapperSet = findClass(packageName);
52+
for (Class<?> mapperClass : mapperSet) {
53+
addMapper(mapperClass);
54+
}
55+
}
56+
/**
57+
* 提供直接调用的方法
58+
* @param packageName
59+
* @return
60+
* @throws IOException
61+
* @throws ClassNotFoundException
62+
*/
63+
public static List<Class> findClass(String packageName) throws IOException, ClassNotFoundException {
64+
return findClass(packageName, new ArrayList<>());
65+
}
66+
67+
/**
68+
*
69+
* @param packageName
70+
* @param clazzs
71+
* @return
72+
* @throws ClassNotFoundException
73+
* @throws IOException
74+
*/
75+
private static List<Class> findClass(String packageName, List<Class> clazzs) throws ClassNotFoundException, IOException {
76+
//将报名替换成目录
77+
String fileName = packageName.replaceAll("\\.", "/");
78+
//通过classloader来获取文件列表
79+
File file = new File(Thread.currentThread().getContextClassLoader().getResource(fileName).getFile());
80+
File[] files = file.listFiles();
81+
for (File f:files) {
82+
//如果是目录,这进一个寻找
83+
if (f.isDirectory()) {
84+
//截取路径最后的文件夹名
85+
String currentPathName = f.getAbsolutePath().substring(f.getAbsolutePath().lastIndexOf(File.separator)+1);
86+
//进一步寻找
87+
findClass(packageName+"."+currentPathName, clazzs);
88+
} else {
89+
//如果是class文件
90+
if (f.getName().endsWith(".class")) {
91+
//反射出实例
92+
Class clazz = Thread.currentThread().getContextClassLoader().loadClass(packageName+"."+f.getName().replace(".class",""));
93+
clazzs.add(clazz);
94+
}
95+
}
96+
}
97+
return clazzs;
98+
}
99+
}
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
package io.kimmking.homework.mockmybatis.session;
2+
3+
import io.kimmking.homework.mockmybatis.binding.MapperRegistry;
4+
5+
/**
6+
* @ClassName DefaultSqlSession
7+
* @Author jackchen
8+
* @Date 2022/8/2 18:16
9+
* @Description TODO
10+
**/
11+
public class DefaultSqlSession implements SqlSession{
12+
13+
private MapperRegistry mapperRegistry;
14+
15+
public DefaultSqlSession(MapperRegistry mapperRegistry) {
16+
this.mapperRegistry = mapperRegistry;
17+
}
18+
19+
@Override
20+
public <T> T selectOne(String statement) {
21+
return null;
22+
}
23+
24+
@Override
25+
public <T> T selectOne(String statement, Object parameter) {
26+
return (T) ("你被代理了!" + "方法:" + statement + " 入参:" + parameter);
27+
}
28+
29+
@Override
30+
public <T> T getMapper(Class<T> type) {
31+
return mapperRegistry.getMapper(type, this);
32+
}
33+
}
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
package io.kimmking.homework.mockmybatis.session;
2+
3+
import io.kimmking.homework.mockmybatis.binding.MapperRegistry;
4+
5+
/**
6+
* @ClassName DefaultSqlSessionFactory
7+
* @Author jackchen
8+
* @Date 2022/8/2 18:19
9+
* @Description TODO
10+
**/
11+
public class DefaultSqlSessionFactory implements SqlSessionFactory{
12+
private final MapperRegistry mapperRegistry;
13+
14+
public DefaultSqlSessionFactory(MapperRegistry mapperRegistry) {
15+
this.mapperRegistry = mapperRegistry;
16+
}
17+
18+
@Override
19+
public SqlSession openSession() {
20+
return new DefaultSqlSession(mapperRegistry);
21+
}
22+
23+
}
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
package io.kimmking.homework.mockmybatis.session;
2+
3+
/**
4+
* @ClassName SqlSession
5+
* @Author jackchen
6+
* @Date 2022/8/2 18:06
7+
* @Description TODO
8+
**/
9+
public interface SqlSession {
10+
/**
11+
* Retrieve a single row mapped from the statement key
12+
* 根据指定的SqlID获取一条记录的封装对象
13+
*
14+
* @param <T> the returned object type 封装之后的对象类型
15+
* @param statement sqlID
16+
* @return Mapped object 封装之后的对象
17+
*/
18+
<T> T selectOne(String statement);
19+
20+
/**
21+
* Retrieve a single row mapped from the statement key and parameter.
22+
* 根据指定的SqlID获取一条记录的封装对象,只不过这个方法容许我们可以给sql传递一些参数
23+
* 一般在实际使用中,这个参数传递的是pojo,或者Map或者ImmutableMap
24+
*
25+
* @param <T> the returned object type
26+
* @param statement Unique identifier matching the statement to use.
27+
* @param parameter A parameter object to pass to the statement.
28+
* @return Mapped object
29+
*/
30+
<T> T selectOne(String statement, Object parameter);
31+
32+
/**
33+
* Retrieves a mapper.
34+
* 得到映射器,这个巧妙的使用了泛型,使得类型安全
35+
*
36+
* @param <T> the mapper type
37+
* @param type Mapper interface class
38+
* @return a mapper bound to this SqlSession
39+
*/
40+
<T> T getMapper(Class<T> type);
41+
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
package io.kimmking.homework.mockmybatis.session;
2+
3+
/**
4+
* @ClassName SqlSessionFactory
5+
* @Author jackchen
6+
* @Date 2022/8/2 18:19
7+
* @Description TODO
8+
**/
9+
public interface SqlSessionFactory {
10+
/**
11+
* 打开一个 session
12+
* @return SqlSession
13+
*/
14+
SqlSession openSession();
15+
}

0 commit comments

Comments
 (0)