脚本宝典收集整理的这篇文章主要介绍了Spring源码(1)mybatis核心原理,脚本宝典觉得挺不错的,现在分享给大家,也给大家做个参考。
静态代理 1 代理类 继承 目标类
2.代理类 和 目标类 实现同一接口 ,代理类里面包含一个目标对象。
显而易见的缺点:产生很多代理类,而且 每一个代理类 只能代理指定的目标类。
动态代理 jdk cglib
jdk的:
Proxy.newProxyInstance 方法,第一个参数是类加载器,第二个参数是被代理类所实现的全部接口,
第三个是实现了invocationHandler接口的实现类 的 对象。
=========用的就是直接产生字节码文件,然后JVM就 class.forname .newInstance()创建代理对象。
我们每次写, 都是写一个DAO的接口。mybatis 是怎么玩的呢?
其实 mybatis 会把对象创建出来,然后把对象给 ioc容器。
mybatis会把接口, 通过 mapPErFactoryBean 生成对象,然后放到IOC中。
怎么生成? 就是通过jdk动态代理。
在使用Mybatis的时候,通过 SQLsession.getMapper(类.class)
的方式,返回一个对象。
这个底层其实就是 proxy.newProxyInstance得到的,也就是代理得到的。
所以:mybatis的和兴功能之一:通过jdk动态代理技术,完成对mapper接口的实例化。
mybatis 通过MapperFactoryBean创建一个对象然后交给Spring容器!!!
class.forname =====得到Class
newInstance=====得到对象。
==============================================
build.gradle中添加依赖:
//mybatis核心依赖
implementation group: 'org.mybatis', name: 'mybatis', version: '3.5.9'
implementation group: 'org.mybatis', name: 'mybatis-spring', version: '2.0.6'
implementation group: 'MySQL', name: 'mysql-connector-java', version: '8.0.27'
//spring
compile(project(":spring-context"))
//数据源
compile(project(":spring-jdbc"))
testCompile group: 'junIT', name: 'junit', version: '4.12'
配置数据源和sqlsessionfactory
@configuration
@MapperScan("wyw")
@componentScan("wyw")
public class MybatisConfig {
@Bean
public DataSource dataSource(){
DriverManagerDataSource driverManagerDataSource
= new DriverManagerDataSource();
driverManagerDataSource.setDriverclassname("com.mysql.jdbc.Driver");
driverManagerDataSource.setPassword("root");
driverManagerDataSource.setUsername("root");
driverManagerDataSource.setUrl("jdbc:mysql://localhost:3306/task3?useUnicode=true&characterEncoding=UTF-8&useSSL=false&serverTimezone=Asia/Shanghai");
return driverManagerDataSource;
}
@Bean
@Autowired
public SqlSessionFactoryBean sqlSessionFactoryBean(DataSource dataSource){
SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean();
sqlSessionFactoryBean.setDataSource(dataSource);
return sqlSessionFactoryBean;
}
}
IndexService中打印:
@Slf4j(topic = "e")
@Component
public class IndexService {
@Autowired
IndexDao indexDao;
public void list(){
List<map<String, Object>> list = indexDao.list();
LOG.debug("list:{}",list);
}
}
主线程看结果:
public static void main(String[] args) {
AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext();
ac.register(MybatisConfig.class);
ac.refresh();
IndexService service = ac.getBean(IndexService.class);
service.list();
}
运行:
==============================
分析核心功能:
在service中调用dao的位置打断点:
可以看到, indexDao 是 MapperProxy类型的对象, 其实就是
InvocationHandler
类型
所以,就是 jdk动态代理来实现的。这其实是个结论,这个结论如何产生的呢。。。。
==============================
MybatisFactoryBean 很明显是mybatis开发的,不是spring开发的。
由上面的逻辑,就可以假设,脱离spring,也可以单纯的通过mybatis得到一个dao对象
官网上的说法得到对象:
environment environment = null;
Configuration configuration = new Configuration(environment);
configuration.addMapper(IndexDao.class);
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(configuration);
SqlSession sqlSession = sqlSessionFactory.openSession();
IndexDao mapper = sqlSession.getMapper(IndexDao.class);
所以
IndexDao mapper = sqlSession.getMapper(IndexDao.class);
可能是这里得到的对象,也可能是之前行得到的然后这里获取。;;也可能不是。
里面有一行:
return mapperProxyFactory.newInstance(sqlSession);
这行代码,也说明两种可能,可能就是在这行创建的对象,也可能是之前产生的这里获取。
return (T) Proxy.newProxyInstance(mapperInterface.getClassLoader(), new Class[] { mapperInterface }, mapperProxy);
第一个是类加载器,第二个是接口,第三个是 实现了 innovationhandler接口的类
所以可以看出,就是这里产生的,而不是之前产生然后拿到。
=================================
如果要模拟mybatis
实现innovationHandler接口的那个类,哟啊重写invoke方法,里面的参数 Method 就是当前调用的方法。
invoke 方法 的大致思路就是,先根据这个方法得到注解,然后通过注解得到sql语句,(配置文件不考虑),然后连接数据库执行sql,最后返回就ok了。
============
小细节:
动态代理底层其实重写了 toString方法,
但是每一个代理对象执行的方法,都要经过 invoke方法,所以在打印的时候可以:
这样子自定义一下就ok了。
以上是脚本宝典为你收集整理的Spring源码(1)mybatis核心原理全部内容,希望文章能够帮你解决Spring源码(1)mybatis核心原理所遇到的问题。
本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
如您有任何意见或建议可联系处理。小编QQ:384754419,请注明来意。