Bootstrap

自研一个简单的类似mybatis框架

解决的问题1:自己的框架如何与springboot进行整合?

  • 自研一个框架如何与springboot进行整合?
    首先我们了解了像mybatis,springmvc,jedis等框架是与springboot已经整合好的
    但是像dubbo等还有很多的框架 没有整合好 我们自己研发的框架要怎样与springboot进行整合.
    读springboot整合mybatis过程
    读配置模块 首先我们找到 AutoConfigurationimportSelector自动加载配置类,
    可以看到在117行添加断点,看执行的调用过程
    在这里插入图片描述
    进入断点,我们发现springboot加载了很多的类,其中每个类都加载了AutoConfiguration这个类
    在这里插入图片描述
    那我们查看Autoconfiguration,是否我们想要被springboot整合也需要写这样的类?
    答案很明显,在AutoConfiguration中既有SQLSessionFactory创建sqlSessionFactory,又有MybatisProperties读取yml文件 所以我们要想写一个类似的mybatis的而且要被springboot加载也需要写这三个类!
    在这里插入图片描述
    找到sqlSessionFactory方法(返回值是一个sqlSessionFactory并放到容器中) 加断点 发现已经进入断点
    在这里插入图片描述
    通过mybatisproperties 读取yml文件
    在这里插入图片描述
    那么springboot是如何发现并整合mybatis的呢?
    我们在maven依赖中找到 springboot-actuator-autoconfigure这个jar包
    找到META-INF/spring.factories中得到答案:存储形式是key:value形式
    Key是springboot固定的形式而value正是MybatisAutoConfiguration也就是说Springboot自己去找META-INF/spring.factories找到需要整合的框架的配置文件进行配置
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    我们自己来实现一个框架,与springboot进行整合
    首先我们需要创建SqlSessionFactory 类,模拟mybatis产生sqlSession访问数据库
/**
 * @author renjiaxing
 *我们创建一个SqlSessionFactory 模拟返回一个sqlSession
 */
public class SqlSessionFactory {
	public String getSqlSession() {
		return "sqlSession";
	}
}

接着我们需要一个MybatisProperties 这个类进行加载yml文件

/**
 * @author renjiaxing
 *读取application.yml中的属性
 */
@ConfigurationProperties(prefix ="com.cy.mybatis" )
public class MybatisProperties {
	private String ip="localhost";
	private String username="root";
	public String getIp() {
		return ip;
	}
	public void setIp(String ip) {
		this.ip = ip;
	}
	public String getUsername() {
		return username;
	}
	public void setUsername(String username) {
		this.username = username;
	}
}

最后我们将这两个类融合到MybatisAutoConfiguration配置类中

//代替sping中的<bean class=SqlSessionFactory>
@Configuration
@EnableConfigurationProperties(MybatisProperties.class)
public class MybatisAutoConfiguration {
	static {
		System.out.println("加载MybatisAutoConfiguration");
	}
	//读取配置属性
	@Resource
	MybatisProperties mybatisProperties;
	//创建核心类,放在容器中
	@Bean
	public SqlSessionFactory sqlSessionFactory() {
		System.out.println("ip="+mybatisProperties.getIp());
		System.out.println("username="+mybatisProperties.getUsername());

		SqlSessionFactory factory=new SqlSessionFactory();
		return factory;
	}
}

最后我们要想被springboot整合还需要做最重要的一步
在这里插入图片描述
在resources目录下创建META-INF/spring.factories文件
在这里插入图片描述

最后我们将写好的程序打包,如下图打包成功
在这里插入图片描述

接下来我们来测试自己写的框架是否能被springboot整合.
我们创建一个测试项目 将我们刚刚打包好依赖添加进去
在这里插入图片描述
写一个测试的controller调用我们之前写好的框架,调用getSqlSession

/**
 * @author renjiaxing
 *尝试使用springboot整合我们所写的框架,并且获取yml文件中的信息
 */
@RestController
public class TestController {
	//从容器中取sqlSessionFactory对象
	@Autowired
	SqlSessionFactory sqlSessionFactory;
	
	@RequestMapping("/test")
	public String test() {
		return sqlSessionFactory.getSqlSession();
	}
}

在yml文件中写入配置信息

com:
   cy:
       mybatis:
              ip: 200.2.2.2
              username: abc

启动项目,访问
在这里插入图片描述
拿到我们sqlsessionfactory方法中的sqlsession并且控制台也拿到了配置信息
在这里插入图片描述
我们完成了自己写的框架与springboot进行整合

解决的问题2:如何让我们的框架更有容错性

  • 我们自己写一个类似mybatis简单的框架,要明白框架的组成,或者是说程序以及软件是由什么组成的?
    [当然在大学中,可能有老师会教软件是由数据结构+算法构成的,但是随着时代的推移,
    我认为软件是由很多的框架单一职责组成的,虽然我没上过!!(spring,springboot将这些框架整合到一起),
    而框架是由很多个模块组成的(模块是由spi标准整合到一起)
    模块又是通过设计模式,数据结构,算法来实现]
    在这里插入图片描述
    两种提供服务的方法:

Spi的介绍:(service provide interface)以接口的形式对外提供服务(优势就是模块可以被替换掉)
Tomcat:以网络的形式对外提供服务

写过一个跟数据库框架,有配置模块,SQL运行模块…很多模块
用spi标准来加载每一个模块,为每个模块提供接口,实现类放在META-INF/Services目录下
在框架中用serviceLoader加载模块
我们通过代码类实现
在这里插入图片描述

/**
 * @author renjiaxing
 *定义模块要实现的功能
 */
public interface config {
	  //加载配置信息
      public void loadConfig();
}

创建一个接口项目,添加一个加载配置信息的方法.
接着我们写一个默认实现类
在这里插入图片描述

/**
 * @author renjiaxing
 *定义接口的默认实现
 */
public class DefaultConfigImpl implements config {
	@Override
	public void loadConfig() {
		System.out.println("框架的默认实现");	
	}
}

我们写好实现类,当别人使用我们所写的框架时,就会有默认服务,但是如果别人发现我们写的代码有bug需要进行修改,我们如何写我们的代码,才能实现别人只需要写一个新的实现类,我们的框架,自己刷新并且继续使用
[Jar包含了什么?
Class文件+META-INF文件夹 spring.factories告诉Spring boot框架自动配置类在哪
Services/接口 放的是类名
]
我们需要添加一个META-INF/services 写一个文件 文件名写的是我们接口的名字
文件中的内容写的是实现类的名字
在这里插入图片描述
写好后我们将程序打包,写一个测试类进行测试.
在这里插入图片描述
在这里插入图片描述
将写好的实现类假如依赖

/**
 * @author renjiaxing
 *测试我们通过spi写的框架在遇到bug时,只需要重新写实现类,框架继续执行
 */
public class App 
{
    public static void main( String[] args )
    {
        System.out.println( "框架启动了, 加载每个模块" );
        ServiceLoader<config> serviceLoader =ServiceLoader.load(config.class);
        Iterator<config> iterator = serviceLoader.iterator();
        while (iterator.hasNext()) {
			config config = iterator.next();
			config.loadConfig();			
		}
    }
}

执行代码
在这里插入图片描述
可以看到此时执行的默认的实现

  • 那么当我们的程序出现了bug需要修改时,我们是否能只是重写一个实现类就可以执行呢?
    在这里插入图片描述
    我们重写一个新的实现类
/**
 * @author renjiaxing
 *使用框架的程序员发现框架的默认的实现由bug 写一个新的实现
 *做框架使用了spi标准,要求实现类必须放在一个文件中文件名必须是接口名 文件内容是实现类名
 * /META-INF/services文件夹中,框架才能使用serviceload才能加载到实现类
 */
public class NewConfigImpl implements config {
	@Override
	public void loadConfig() {
	 System.out.println("新的实现");
	}
}

同样的添加一个META-INF/services 写一个文件 文件名写的是我们接口的名字
文件中的内容写的是新的实现类的名字
在这里插入图片描述
同样的打一个包,在spi-mybatis项目中添加新的依赖
在这里插入图片描述
执行代码
在这里插入图片描述
新的代码已经执行
根据断点看源码我们能够了解sql的执行过程是
简单的流程就是
DefaultSqlSession–>executor–>statementHandler–>jdbc
加上缓存后的流程就是
在这里插入图片描述
Spring框架中bean class=SqlSessionFactoryBean 创建了几个对象?
两个:如果是SqlSessionFactory创建一个
SqlSessionfactoryBean返回一个SqlSessionfactoryBean,
它又实现了FactoryBean,有一个getObject方法返回一个SqlSessionFactory
所以是两个对象

;