Spring整合MyBatis的底层原理分为以下几点:1、Mybatis如何生成代理对象;2、Spring中如何声明一个bean;3、模拟代理对象转化Spring的bean过程。其中,Mybatis如何生成代理对象在org.mybatis:mybatis.jar包中给我们提供了一些方法。
一、Mybatis如何生成代理对象
在 org.mybatis:mybatis.jar包中给我们提供了一些方法。下面代码是运用mybatis来生成代理对象。
public class MybatisTest {
public static void main(String[] args) throws IOException {
// 1. 创建SqlSessionFactoryBuilder对象
SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();
// 2. 加载SqlMapConfig.xml配置文件
InputStream inputStream = Resources.getResourceAsStream("mybatis.xml");
// 3. 创建SqlSessionFactory对象
SqlSessionFactory sqlSessionFactory = sqlSessionFactoryBuilder.build(inputStream);
// 4. 创建SqlSession对象
SqlSession sqlSession = sqlSessionFactory.openSession();
// 5.执行sql
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);// 获得一个(动态代理)UserMapper接口的实现类对象
System.out.println(userMapper.selectById());
// 6.释放资源
sqlSession.close();
}
}
二、Spring中如何声明一个bean
定义bean分为两种方式:
名列前茅种:声明式,例如:我们通常使用的@Bean注解,@Service注解,@Component注解等等。
第二种:编程式 ,运用BeanDefinition来创建一个bean,下面看代码:
public class User {
public void fff(){
System.out.println("初始化方法");
}
}
public static void main(String[] args) {
//使用AnnotationConfigApplicationContext可以实现基于Java的配置类加载Spring的应用上下文。避免使用application.xml进行配置。相比XML配置,更加便捷。
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();
applicationContext.register(AppConfig.class);
//获取beanDefinition对象
AbstractBeanDefinition beanDefinition = BeanDefinitionBuilder.genericBeanDefinition().getBeanDefinition();
//创建User类的bean
beanDefinition.setBeanClass(User.class);
beanDefinition.setScope("prototype"); //bean单例模式改为原型模式
beanDefinition.setInitMethodName("fff"); //设置bean的初始化方法
//设置bean的名称
applicationContext.registerBeanDefinition("xxx",beanDefinition);
applicationContext.refresh();
/**
* 打印结果
* 初始化方法
* com.example.service.User@3b94d659
* 初始化方法
* com.example.service.User@24b1d79b
* 初始化方法
* com.example.service.User@68ceda24
*/
System.out.println(applicationContext.getBean("xxx"));
System.out.println(applicationContext.getBean("xxx"));
System.out.println(applicationContext.getBean("xxx"));
// UserService userService = applicationContext.getBean(UserService.class);
// userService.test();
}
通过上述代码我们可以使用BeanDefinition来创建一个bean。但是如果我的User类如果是一个接口通过BeanDefinition就不能实现了。我们可以通过FactoryBean来创建bean。
在下面代码:由于beanDefinition.setBeanClass(FactoryBeanTest.class);这行代码我们创建的是FactoryBeanTest.class这个类型的bean,但是FactoryBeanTest 类实现了FactoryBean这个接口最后返回给我们一个User类型的bean。这样我们就实现了动态的获取bean。
public class FactoryBeanTest implements FactoryBean {
//getObject方法返回的bean,会放到spring容器里面去
@Override
public Object getObject() throws Exception {
return new User();
}
//getObjectType方法是返回bean的类型
@Override
public Class<?> getObjectType() {
return null;
}
}
public class TestApplication {
public static void main(String[] args) {
//使用AnnotationConfigApplicationContext可以实现基于Java的配置类加载Spring的应用上下文。避免使用application.xml进行配置。相比XML配置,更加便捷。
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();
applicationContext.register(AppConfig.class);
//获取beanDefinition对象
AbstractBeanDefinition beanDefinition = BeanDefinitionBuilder.genericBeanDefinition().getBeanDefinition();
//创建User类的bean
beanDefinition.setBeanClass(FactoryBeanTest.class);
//设置bean的名称
applicationContext.registerBeanDefinition("xxx",beanDefinition);
applicationContext.refresh();
System.out.println(applicationContext.getBean("xxx"));
}
}
三、模拟代理对象转化Spring的bean过程
首先我们通过Proxy.newProxyInstance方法去模拟一个代理对象,然后通过FactoryBean将这个代理对象放入SpringBean容器中。然后通过调用UserService.test方法我们可以发现:在执行UserService.test方法时会调用userMapper代理对象的selectById())的方法,
那么在调用代理对象时会先调用代理对象的代理逻辑里面也就是invoke方法,然后再去调用代理对象的selectById())的方法。
这样我们就做到了将mybatis的代理对象转化位bean放入到spring容器中。
public class FactoryBeanTest implements FactoryBean {
@Override
public Object getObject() throws Exception {
/**
* 参数:类加载器,代理的接口,代理的逻辑
*/
Object proxyInstance = Proxy.newProxyInstance(FactoryBeanTest.class.getClassLoader(), new Class[]{UserMapper.class}, new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println(method.getName());
return null;
}
});
return proxyInstance;
}
@Override
public Class<?> getObjectType() {
return UserMapper.class;
}
}
/**
* 在spring boot中设置的IOC容器中设置包扫描
*/
@ComponentScan("com.example.*")
@Configuration
public class AppConfig {
}
public class TestApplication {
public static void main(String[] args) {
//使用AnnotationConfigApplicationContext可以实现基于Java的配置类加载Spring的应用上下文。避免使用application.xml进行配置。相比XML配置,更加便捷。
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();
applicationContext.register(AppConfig.class);
//获取beanDefinition对象
AbstractBeanDefinition beanDefinition = BeanDefinitionBuilder.genericBeanDefinition().getBeanDefinition();
//创建User类的bean
beanDefinition.setBeanClass(FactoryBeanTest.class);
//设置bean的名称
applicationContext.registerBeanDefinition("xxx",beanDefinition);
applicationContext.refresh();
UserService userService = applicationContext.getBean(UserService.class);
userService.test();
}
}
来源:本文为CSDN博主「愉悦滴帮主)」的原创文章
原文链接:https://blog.csdn.net/qq_45065241/article/details/117526487
延伸阅读
Mybatis是什么
MyBatis本是apache的一个开源项目iBatis,2010年这个项目由apache software foundation迁移到了google code,并且改名为MyBatis。2013年11月迁移到Github。
iBATIS一词来源于“internet”和“abatis”的组合,是一个基于Java的持久层框架。iBATIS提供的持久层框架包括SQL Maps和Data Access Objects(DAOs)。
MyBatis 是一款优异的持久层框架,它支持定制化 SQL、存储过程以及高级映射。MyBatis 避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集。MyBatis 可以使用简单的 XML 或注解来配置和映射原生信息,将接口和 Java 的 POJOs(Plain Ordinary Java Object,普通的 Java对象)映射成数据库中的记录。
MyBatis特点
- 简单易学:本身就很小且简单。没有任何第三方依赖,最简单安装只要两个jar文件+配置几个sql映射文件。易于学习,易于使用。通过文档和源代码,可以比较完全的掌握它的设计思路和实现。
- 灵活:mybatis不会对应用程序或者数据库的现有设计强加任何影响。 sql写在xml里,便于统一管理和优化。通过sql语句可以满足操作数据库的所有需求。
- 解除sql与程序代码的耦合:通过提供DAO层,将业务逻辑和数据访问逻辑分离,使系统的设计更清晰,更易维护,更易单元测试。sql和代码的分离,提高了可维护性。
- 提供映射标签,支持对象与数据库的ORM字段关系映射。
- 提供对象关系映射标签,支持对象关系组建维护。
- 提供xml标签,支持编写动态sql。
文章标题:Spring和Mybatis的底层是什么,发布者:小编,转载请注明出处:https://worktile.com/kb/p/38809