当前位置:首页 > 经验 >

mybatis简单示例(mybatis例子)

来源:原点资讯(www.yd166.com)时间:2022-10-29 11:54:56作者:YD166手机阅读>>

CommandLineRunner

这个是Spring Boot提供扩展接口,这个接口也只有一个方法:run(String... args),触发时机为整个项目启动完毕后,自动执行。如果有多个 CommandLineRunner,可以利用 @Order注解 来进行排序,值越小越优先执行。使用场景:用户扩展此接口,进行启动项目之后一些业务的预处理。

@Component @Order(1) public class MyCommandLineRunner implements CommandLineRunner { @Override public void run(String... args) throws Exception { System.out.println("MyCommandLineRunner run args:" args); } }

@Component @Order(0) public class MyTwoCommandLineRunner implements CommandLineRunner { @Override public void run(String... args) throws Exception { System.out.println("MyTwoCommandLineRunner run args:" args); } }

mybatis简单示例,mybatis例子(9)

ApplicationListener

ApplicationListener 可以监听某个事件的 event,触发时机可以穿插在业务方法执行过程中,用户可以自定义某个业务事件;但是 spring 内部也有一些内置事件,这种事件,可以穿插在启动调用中。我们也可以利用这个特性,来自己做一些内置事件的监听器来达到和前面一些触发点大致相同的事情。接下来罗列下 spring 主要的内置事件:

· ContextRefreshedEvent

· ApplicationContext 被初始化或刷新时,该事件被发布。这也可以在 ConfigurableApplicationContext 接口中使用 refresh() 方法来发生。此处的初始化是指:所有的 Bean 被成功装载,后处理 Bean 被检测并激活,所有 Singleton Bean 被预实例化,ApplicationContext 容器已就绪可用。

· ContextStartedEvent

· 当使用 ConfigurableApplicationContext (ApplicationContext 子接口)接口中的 start() 方法启动 ApplicationContext 时,该事件被发布。你可以调查你的数据库,或者你可以在接受到这个事件后重启任何停止的应用程序。

· ContextStoppedEvent

· 当使用 ConfigurableApplicationContext 接口中的 stop() 停止 ApplicationContext 时,发布这个事件。你可以在接受到这个事件后做必要的清理的工作

· ContextClosedEvent

· 当使用 ConfigurableApplicationContext 接口中的 close() 方法关闭 ApplicationContext 时,该事件被发布。一个已关闭的上下文到达生命周期末端;它不能被刷新或重启

· RequestHandledEvent

· 这是一个 web-specific 事件,告诉所有 bean HTTP 请求已经被服务。只能应用于使用 DispatcherServlet 的 Web 应用。在使用 Spring 作为前端的 MVC 控制器时,当 Spring 处理用户请求结束后,系统会自动触发该事件

@Configuration public class MyApplicationListener implements ApplicationListener { @Override public void onApplicationEvent(ApplicationEvent applicationEvent) { System.out.println("MyApplicationListener onApplicationEvent"); } } BeanNameAware

BeanNameAware也是 Aware 接口扩展的子接口,触发点在 bean 的初始化之前,也就是 postProcessBeforeInitialization 之前

如果bean实现了BeanNameAware接口,spring将bean的id传给setBeanName()方法;这个类的触发点方法只有一个:setBeanName使用场景为:用户可以扩展这个点,在初始化 bean 之前拿到 spring 容器中注册的的 beanName,来自行修改这个 ;

@Component public class MyBeanNameAware implements BeanNameAware { @Override public void setBeanName(String s) { System.out.println("setBeanName:" s); } } BeanFactoryAware

BeanFactoryAware也是 Aware 接口扩展的子接口,只有一个触发点,发生在 bean 的实例化之后,注入属性之前,也就是 Setter 之前。这个类的扩展点方法为 setBeanFactory,可以拿到 BeanFactory 这个属性。使用场景为,你可以在 bean 实例化之后,但还未初始化之前,拿到 BeanFactory,在这个时候,可以对每个 bean 作特殊化的定制。也或者可以把 BeanFactory 拿到进行缓存,日后使用,如果bean实现了BeanFactoryAware接口,spring将调用setBeanFactory方法,将BeanFactory实例传进来;

@Component public class MyBeanFactoryAware implements BeanFactoryAware { @Override public void setBeanFactory(BeanFactory beanFactory) throws BeansException { System.out.println("MyBeanFactoryAware setBeanFactory:" beanFactory.getBean("myBeanFactoryAware").getClass().getSimpleName()); } } Bean初始化及销毁回调方法

  • InitializingBean是用来初始化 bean 的。InitializingBean 接口为 bean 提供了初始化方法的方式,它只包括 afterPropertiesSet 方法,凡是继承该接口的类,在初始化 bean 的时候都会执行该方法。这个扩展点的触发时机在 postProcessAfterInitialization 之前。
  • DisposableBean这个扩展点也只有一个方法:destroy(),其触发时机为当此对象销毁时,会自动执行这个方法。比如说运行 applicationContext.registerShutdownHook 时,就会触发这个方法。
  • @PostConstruct这个并不算一个扩展点,其实就是一个标注。其作用是在 bean 的初始化阶段,如果对一个方法标注了 @PostConstruct,会先调用这个方法。这里重点是要关注下这个标准的触发点,这个触发点是在 postProcessBeforeInitialization 之后,InitializingBean.afterPropertiesSet 之前。使用场景:用户可以对某一方法进行标注,来进行初始化某一个属性
  • @PreDestroy修饰的方法会在服务器关闭Spring容器的时候运行,并且只会调用一次

使用场景:用户实现此接口,来进行系统启动的时候一些业务指标的初始化工作。

@Repository public class Student implements InitializingBean, DisposableBean { @PostConstruct public void init() throws Exception { System.out.println("Student init"); } @PreDestroy public void close() throws Exception { System.out.println("Student close"); } @Override public void destroy() throws Exception { System.out.println("Student destroy"); } @Override public void afterPropertiesSet() throws Exception { System.out.println("Student afterPropertiesSet"); } }

mybatis简单示例,mybatis例子(10)

整合示例

mybatis-spring gitee源码地址
https://gitee.com/yongzhebuju/mybatis-spring

我们从这些 Spring&Spring Boot 的扩展点当中,大致可以窥视到整个 bean 的生命周期。在业务开发或者写中间件业务的时候,可以合理利用 Spring 提供给我们的扩展点,在 Spring 启动的各个阶段内做一些事情,以达到自定义初始化的目的。接下来我们一起学习一个常见Mybatis和Spring整合开发简易示例,上面内容我们初步对于Spring扩展点有了一些理解,由于本人阅读过部分Mybatic与Spring整合源码,思路也是来源于此,由于目前是简易示例,不在工程加入Mybatis依赖,着重在整合部分

思考问题
  • Spring的Bean是如何生成的?
  • Spring提供哪些扩展点来整合第三方框架?
  • Spring是如何来整理Mybatis的?Mybatis代理对象都是接口,不能直接通过New方式将Mapper Bean注册Spring容器里
主体思路
  • 首先可以明确一点,我们需要利用到Jdk动态代理及反射机制
  • 借助FactoryBean特性,FactoryBean可以返回动态代理的对象及类型
  • 通过ImportBeanDefinitionRegistrar通过Import注解将FactoryBean通过BeanDefinition注册到BeanDefinitionRegistry通过后续Bean的生命周期最终放到Spring的容器里
Mybatic快速入门

从官网的就可以直接找到Java编程快速入门** ,这里只是大概说明一下**

String resource = "org/mybatis/example/mybatis-config.xml"; InputStream inputStream = Resources.getResourceAsStream(resource); SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream); try (SqlSession session = sqlSessionFactory.openSession()) { BlogMapper mapper = session.getMapper(BlogMapper.class); Blog blog = mapper.selectBlog(101); } 整合示例实现

pom文件

<?xml version="1.0" encoding="UTF-8"?> <project xmlns="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>4.0.0</modelVersion> <groupId>com.itxs</groupId> <artifactId>mybatis-spring</artifactId> <version>1.0-SNAPSHOT</version> <properties> <maven.compiler.source>8</maven.compiler.source> <maven.compiler.target>8</maven.compiler.target> </properties> <dependencies> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>5.3.9</version> </dependency> </dependencies> </project>

mybatis简单示例,mybatis例子(11)

注解接口,通过@Import同时将ItxsImportBeanDefinitionRegistrar导入到Spring容器里

@Retention(RetentionPolicy.RUNTIME) @Import({ItxsImportBeanDefinitionRegistrar.class}) public @interface ItxsScan { String value() default ""; }

配置类,@ItxsScan为我们自定义的注解,主要标记扫描mapper路径

@Configuration @ComponentScan({"com.itxs"}) @ItxsScan("com.itxs.dao") public class AppConfig { }

mapper接口,@ItxsSelect为我们自定义的注解,主要标记mapper接口方法sql语句

package com.itxs.dao; import com.itxs.annotation.ItxsSelect; import com.itxs.pojo.User; public interface UserMapper { @ItxsSelect("select * from user where user_id = #{userId}") User selectByUserId(Integer userId); }

service实现类

@Component public class UserService { @Autowired UserMapper userMapper; @Autowired OrderMapper orderMapper; public void getUser(){ userMapper.selectByUserId(1); orderMapper.selectByOrderId(1); } }

FactoryBean实现,这里通过构造函数传入接口的Class类型,将类型通过Jdk动态代理生成并返回对象,当调用目标对象后会执行代理对象invoke方法,从invoke方法通过反射与注解获取到sql语句,后续流程就可以利用Mybatis提供操作数据库流程,这里就不继续深入了

package com.itxs.utils; import com.itxs.annotation.ItxsSelect; import org.springframework.beans.factory.FactoryBean; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; public class ItxsFactoryBean implements FactoryBean { private Class mapper; public ItxsFactoryBean(Class mapper) { this.mapper = mapper; } @Override public Object getObject() throws Exception { //使用动态代理机制 Object o = Proxy.newProxyInstance(ItxsFactoryBean.class.getClassLoader(), new Class[]{mapper}, new InvocationHandler() { @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { if (Object.class.equals(method.getDeclaringClass())){ return method.invoke(this,args); } ItxsSelect annotation = method.getAnnotation(ItxsSelect.class); System.out.println("调用方法名称是" method.getName() ",sql语句为" annotation.value()); //后面可执行Mybatic操作数据库的相关操作 return null; } }); return o; } @Override public Class<?> getObjectType() { return mapper; } }

ImportBeanDefinitionRegistrar的实现,通过获取@import上的注解找到mapper的扫描路径,通过classLoader加载磁盘下Class文件生成BeanDefinition并设置构造函数mapper类型参数,最终将BeanDefinition注册到BeanDefinitionRegistry

package com.itxs.utils; import com.itxs.annotation.ItxsScan; import com.itxs.dao.OrderMapper; import com.itxs.dao.UserMapper; import org.springframework.beans.factory.support.AbstractBeanDefinition; import org.springframework.beans.factory.support.BeanDefinitionBuilder; import org.springframework.beans.factory.support.BeanDefinitionRegistry; import org.springframework.beans.factory.support.BeanNameGenerator; import org.springframework.context.annotation.ImportBeanDefinitionRegistrar; import org.springframework.core.type.AnnotationMetadata; import java.io.File; import java.net.URL; import java.util.ArrayList; import java.util.List; import java.util.Map; public class ItxsImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar { @Override public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry, BeanNameGenerator importBeanNameGenerator) { //获取注解ItxsScan对象,并取出value值作为扫描的路径 Map<String, Object> annotationAttributes = importingClassMetadata.getAnnotationAttributes(ItxsScan.class.getName()); String mapperPath = annotationAttributes.get("value").toString(); List<Class> mappers = scan(mapperPath); for (Class mapper : mappers) { BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(); AbstractBeanDefinition beanDefinition = builder.getBeanDefinition(); beanDefinition.setBeanClass(ItxsFactoryBean.class); beanDefinition.getConstructorArgumentValues().addGenericArgumentValue(mapper); registry.registerBeanDefinition(StringUtils.toLowerCaseFirstOne(mapper.getSimpleName()),beanDefinition); } } private List<Class> scan(String path) { List<Class> classList = new ArrayList<Class>(); path = path.replace(".", "/"); ClassLoader classLoader = ItxsImportBeanDefinitionRegistrar.class.getClassLoader(); URL url = classLoader.getResource(path); File file = new File(url.getFile()); if (file.isDirectory()) { File[] files = file.listFiles(); for (int i = 0; i < files.length; i ) { String absolutePath = files[i].getAbsolutePath(); absolutePath = absolutePath.substring(absolutePath.indexOf("com"), absolutePath.indexOf(".class")); absolutePath = absolutePath.replace("\\", "."); try { Class<?> aClass = classLoader.loadClass(absolutePath); classList.add(aClass); } catch (ClassNotFoundException e) { e.printStackTrace(); } } } return classList; } }

Main程序

package com.itxs; import com.itxs.config.AppConfig; import com.itxs.service.UserService; import org.springframework.context.annotation.AnnotationConfigApplicationContext; public class MybatisApplication { public static void main(String[] args) { AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(AppConfig.class); UserService userService = applicationContext.getBean("userService", UserService.class); userService.getUser(); } }

运行结果

mybatis简单示例,mybatis例子(12)

栏目热文

mybatis基本工作流程(mybatis中的基础知识和快速入门)

mybatis基本工作流程(mybatis中的基础知识和快速入门)

1、首先是读取Mybatis的核心配置文件Mybaits-config.xml,该文件主要是配置了数据库的连接信息、用户...

2022-10-29 11:42:24查看全文 >>

mybatis原理通俗易懂(my batis的工作原理)

mybatis原理通俗易懂(my batis的工作原理)

近来想写一个Mybatis的分页插件,但是在写插件之前肯定要了解一下mybatis具体的工作原理吧,于是边参考别人的博客...

2022-10-29 11:56:10查看全文 >>

mybatis源码深度解析(mybatis源码详细讲解)

mybatis源码深度解析(mybatis源码详细讲解)

一、前言1、mybatis框架图如上为mybatis的框架图,在这篇文章中通过源码来重点看下数据处理层中的参数映射,SQ...

2022-10-29 12:00:28查看全文 >>

mybatisplus优缺点(mybatis优缺点)

mybatisplus优缺点(mybatis优缺点)

在之前发表的文章中有说过mybatis,没看过的可以去看一看,今天来说一说他的升级版本,简而言之,就是mybatis-p...

2022-10-29 11:54:17查看全文 >>

mybatis基础知识整理(mybatis初学者基础知识)

mybatis基础知识整理(mybatis初学者基础知识)

Mybatis简介原始jdbc操作(查询数据)原始jdbc操作(插入数据)原始jdbc操作的分析原始jdbc开发存在的问...

2022-10-29 12:07:42查看全文 >>

mybatis菜鸟教程(mybatis学习手册)

mybatis菜鸟教程(mybatis学习手册)

mybatis基本配置及执行使用了mybatis首先需要两个配置文件,一个是mybatis-config.xml,是my...

2022-10-29 11:29:14查看全文 >>

mybatis工作原理通俗理解(mybatis真实原理)

mybatis工作原理通俗理解(mybatis真实原理)

作者:vivo互联网服务器团队-Zhang Peng一、MyBatis 完整示例这里,我将以一个入门级的示例来演示 My...

2022-10-29 11:27:50查看全文 >>

mybatis插入时间参数(mybatis接收日期参数)

mybatis插入时间参数(mybatis接收日期参数)

介绍MyBatis Generator的作用就是根据数据库中的表结构,帮我们自动生成和表结构相同的实体类,mapper接...

2022-10-29 12:02:57查看全文 >>

mybatis底层原理分析(mybatis底层原理图)

mybatis底层原理分析(mybatis底层原理图)

此篇文章讲述了MyBatis的原理,非常简单却很实用。持续分享Java技术干货,欢迎关注我。前言MyBatis 是一个被...

2022-10-29 11:32:36查看全文 >>

mybatis官方文档中文(mybatis免费)

mybatis官方文档中文(mybatis免费)

官网地址:https://github.com/mybatis/mybatis-3一个简单的mybatis-demo简概...

2022-10-29 11:32:46查看全文 >>

文档排行