1.spring的扩展:
我们知道spring和mybatis整合的故事,Spring 2.0 只支持 iBatis 2.0。那么,我们就想将 MyBatis3 的支持添加到 Spring 3.0 中。不幸的是,Spring 3.0 的开发在 MyBatis 3.0 官方发布前就结束了。由于 Spring 开发团队不想发布一个基于未发布版的 MyBatis 的整合支持,如果要获得 Spring 官方的支持,只能等待下一次的发布了。基于在 Spring 中对 MyBatis 提供支持的兴趣,MyBatis 社区认为,应该开始召集有兴趣参与其中的贡献者们,将对 Spring 的集成作为 MyBatis 的一个社区子项目。
什么是mybatis-spring呢?
MyBatis-Spring 会帮助你将 MyBatis 代码无缝地整合到 Spring 中。它将允许 MyBatis 参与到 Spring 的事务管理之中,创建映射器 mapper 和 SqlSession 并注入到 bean 中,
以及将 Mybatis 的异常转换为 Spring 的 DataAccessException。最终,可以做到应用代码不依赖于 MyBatis,Spring 或 MyBatis-Spring。
2.mybatis-spring的使用
<1>pom.xml
<?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>org.example</groupId> <artifactId>springTest002</artifactId> <version>1.0-SNAPSHOT</version> <dependencies> <!-- spring的依赖 --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>5.2.9.RELEASE</version> </dependency> <!-- mybatis的依赖 --> <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis</artifactId> <version>3.5.5</version> </dependency> <!-- mybatis-spring 依赖 --> <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis-spring</artifactId> <version>2.0.5</version> </dependency> <!-- 数据库引擎 --> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>5.1.49</version> </dependency> <!-- spring-web --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-web</artifactId> <version>5.2.9.RELEASE</version> </dependency> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.13</version> <scope>compile</scope> </dependency> <!-- https://mvnrepository.com/artifact/org.springframework/spring-jdbc --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-jdbc</artifactId> <version>5.2.9.RELEASE</version> </dependency> </dependencies> </project>
<2>AppConfig.java
package config; import mapper.UserMapper; import org.apache.ibatis.datasource.pooled.PooledDataSource; import org.apache.ibatis.session.SqlSessionFactory; import org.mybatis.spring.SqlSessionFactoryBean; import org.mybatis.spring.SqlSessionTemplate; import org.mybatis.spring.mapper.MapperFactoryBean; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import javax.sql.DataSource; @Configuration public class AppConfig { @Bean public DataSource dataSource(){ PooledDataSource dataSource = new PooledDataSource(); dataSource.setDriver("com.mysql.jdbc.Driver"); dataSource.setUrl("jdbc:mysql://localhost:3306/springtest"); dataSource.setUsername("root"); dataSource.setPassword("root"); return dataSource; } @Bean public SqlSessionFactory sqlSessionFactory() throws Exception { SqlSessionFactoryBean factoryBean = new SqlSessionFactoryBean(); factoryBean.setDataSource(dataSource()); return factoryBean.getObject(); } // @Bean // public UserMapper userMapper() throws Exception { // SqlSessionTemplate sqlSessionTemplate = new SqlSessionTemplate(sqlSessionFactory()); // return sqlSessionTemplate.getMapper(UserMapper.class); // } @Bean public MapperFactoryBean<UserMapper> userMapper() throws Exception { MapperFactoryBean<UserMapper> factoryBean = new MapperFactoryBean<UserMapper>(UserMapper.class); factoryBean.setSqlSessionFactory(sqlSessionFactory()); return factoryBean; } }
<3>UserMapper.java
package mapper; import org.apache.ibatis.annotations.Param; import org.apache.ibatis.annotations.Select; import pojo.User; public interface UserMapper { @Select("SELECT * FROM student WHERE id = #{userId}") User getUser(@Param("userId") String userId); }
<4>Test.java
public class Test01 { @Test public void hello(){ System.out.println("aaaa"); ApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class); UserMapper userMapper = (UserMapper)context.getBean("userMapper"); User user = userMapper.getUser("8"); System.out.println(user); } }
3.实现原理:
<1>创建一个MyFactoryBean 去实现 FactoryBean 接口FactoryBean的2个方法。
package bean; import core.MyInvocationHandler; import mapper.UserMapper; import org.springframework.beans.factory.FactoryBean; import java.lang.reflect.Proxy; import java.security.PublicKey; public class MyFactoryBean implements FactoryBean { public Class MapperInterface; public MyFactoryBean(Class mapperInterface) { MapperInterface = mapperInterface; } public Object getObject() throws Exception { Object o = Proxy.newProxyInstance(this.getClass().getClassLoader(), new Class[]{MapperInterface}, new MyInvocationHandler()); return o; } public Class<?> getObjectType() { return MapperInterface; } }
<2>创建一个MyImportBeanDefinitionRegister 去实现 ImportBeanDefinitionRegister接口。
public class MyImportBeanDefinitionRegister implements ImportBeanDefinitionRegistrar { public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) { RootBeanDefinition beanDefinition = new RootBeanDefinition(MyFactoryBean.class); beanDefinition.getConstructorArgumentValues().addGenericArgumentValue("mapper.UserMapper"); registry.registerBeanDefinition("userMapper",beanDefinition); RootBeanDefinition beanDefinition2 = new RootBeanDefinition(MyFactoryBean.class); beanDefinition2.getConstructorArgumentValues().addGenericArgumentValue("mapper.AccountMapper"); registry.registerBeanDefinition("accountMapper",beanDefinition2); } }
<3>创建AppConfig.java
@Configuration @ComponentScan("bean") @Import(MyImportBeanDefinitionRegister.class) public class AppConfig { }
<4>Test.java
public class Test01 { @Test public void a() { ApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class); UserMapper userMapper = (UserMapper)context.getBean("userMapper"); userMapper.queryList(); AccountMapper accountMapper = (AccountMapper)context.getBean("accountMapper"); accountMapper.queryList(); } }