mybatis简单示例,mybatis例子

首页 > 经验 > 作者:YD1662022-10-29 11:54:56

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初始化及销毁回调方法

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

@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依赖,着重在整合部分

思考问题主体思路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)

上一页1234下一页

栏目热文

文档排行

本站推荐

Copyright © 2018 - 2021 www.yd166.com., All Rights Reserved.