mybaits与spring整合
思考如果需要整合的话,我们mybaits需要做什么事情呢?
1.肯定是要把我们的Mapper文件注入到我们的springIOC容器里面
2.而且还要为我们的Mapper文件的接口创建动态代理对象
我们来看整合需要的配置文件
<!-- sqlSessionFactory 1.spring-mybaits整合-->
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<!-- 加载 MyBatis 的配置文件 -->
<!--<property name="configLocation" value="SqlMapConfig.xml"/>-->
<property name="mapperLocations" value="classpath:mapper/*.xml"></property>
<!-- 数据源 -->
<property name="dataSource" ref="dataSource"/>
</bean>
<!-- Mapper 扫描器 2.spring-mybaits整合-->
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<!-- 扫描 cn.wmyskxz.mapper 包下的组件 -->
<property name="basePackage" value="com.tx.mapper"/>
</bean>
我们今天重点来讲第二个:org.mybatis.spring.mapper.MapperScannerConfigurer
查看源码:
实现了:BeanDefinitionRegistryPostProcessor接口
实现postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry)方法
:该方法是往spring中的beanDefintionMap里面注册一个bean定义对象
DefaultListableBeanFactory:
beanDefinitionMap:中保存了bean的定义信息,spring会根据这些定义的信息,创建具体对应的对象
BeanDefinition
ClassPathMapperScanner扫描我们的mapper,添加到beanDefintionMap,修改mapper的beanClass为(我们都知道mapper是接口,不能创建对象,所以我们修改这个bean的class为MapperFactoryBean):
MapperFactoryBean
MapperFactoryBean:implements FactoryBean接口,这里返回代理对象就是调用sqlsession的getMapper方法,因为这里我们需要SqlSessionFacotory
MapperFactoryBean:继承了SqlSessionDaoSupport,前面修改了注入模型,所以这里会根据set方法来注入SqlSessionFacotry,注意spring的单例池中是有SqlSessionFacotry对象的哈!
至此!!简单的逻辑基本及已经完成!
1.完成了 把mapper加入到IOC容器中!
2.也完成了返回代理对象!
mybaits开发人员太厉害了!!
案例
下面就是我们自己根据前面学到的写一个
首先定义一个类似于扫描的,把我们扫描到的所有mapper文件全部加入到bean定义的map中去,所以这里也要实现spring的接口:BeanDefinitionRegistryPostProcessor
public class SelfDefinetion implements BeanDefinitionRegistryPostProcessor {
@Override
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry beanDefinitionRegistry) throws BeansException {
//向beanDefinitionRegistry 添加一个mapper
//也可以循环的添加,暂时举一个例子
BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(SelfMapper.class);
//获取selfMapper 的bean定义信息
GenericBeanDefinition beanDefinition = (GenericBeanDefinition) builder.getBeanDefinition();
//修改mapper的beanClass信息,因为接口是不能创建对象的
/**
* 所以
* 1.这里我们需要一个可以让我们自己返回我们需要的代理类:FactoryBean
* 2.返回代理对象就需要调用我们的sqlSession的getMapper(),方法返回一个动态代理类:SelfSqlSessionDao
* 所以这里才继承SelfSqlSessionDao,通过改变注入模型注入sqlSessionFactory,然后在获取sqlSession
*
*/
beanDefinition.setBeanClass(SelfFatcoryBean.class); //这里我们把beanClass修改SelfFatcoryBean
/**
* 2.1 这里修改注入模型就是为了让我们的SelfSqlSessionDao里面的sqlSessionFactory注入值
*/
beanDefinition.setAutowireMode(AbstractBeanDefinition.AUTOWIRE_BY_TYPE);
beanDefinitionRegistry.registerBeanDefinition("selfMapper",beanDefinition);
}
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory configurableListableBeanFactory) throws BeansException {
}
向bean定义的map中加入了mapper的bean定义信息,也修改了beanClass为:
SelfFatcoryBean(接口是不能创建对象的) 所以这里我们要写我们的:SelfFatcoryBean
这里我们知道要完成2件事情:
1.返回自定义代理对象:实现FactoryBean
2.既然要返回代理对象,肯定就要调用我们sqlSession的getMapper()方法,所以肯定要注入我们的SqlsessionFactory,
所以继承:SelfSqlSessionDao
public class SelfFatcoryBean extends SelfSqlSessionDao implements FactoryBean{
//这里我们返回一个具体的代理对象。这里我们暂时默认设置为静态代理吧
@Override
public Object getObject(){
// new SelfMapperProxy(); //返回我们定义的self Mapper的静态代理对象
//升级:改成我们的动态代理 因为下面需要一个动态代理的一个class,所以这里我们要传入一个信息
System.out.println(this.getSqlSessionFactory()+"验证修改注入模型,是否会注入数据======sqlSession====太厉害 了,真的注入成功了");
//Proxy.newProxyInstance(UserMapper.class.getClassLoader(),clazz,new SelfInvocation());
System.out.println(this.getSqlSession()+"sqlSession的值"); //这里创建了session
return this.getSqlSession().getMapper(SelfMapper.class); //这里mybaits会帮我们创建一个动态代理对象
}
@Override
public Class<?> getObjectType() {
// return SelfMapperProxy.class;
return SelfMapper.class;
}
所以肯定要注入我们的SqlsessionFactory,前面修改注入模型,就是为了这里能够注入SqlsessionFactory对象,来获取sqlSession对象,调用getMapper()方法!
/**
* 我们通过改变beanDefineMap里面注入模型,我们查看sqlSessionTemplate是否会注入成功
*/
public class SelfSqlSessionDao {
private SqlSessionFactory sqlSessionFactory;
public SqlSession getSqlSession(){
return new SqlSessionTemplate(sqlSessionFactory);
}
public SqlSessionFactory getSqlSessionFactory() {
return sqlSessionFactory;
}
public void setSqlSessionFactory(SqlSessionFactory sqlSessionFactory) {
this.sqlSessionFactory = sqlSessionFactory;
}
}
在我们的xml文件中配置我们自己的类:
<!-- 自定义的一个-->
<bean class="com.tx.service.SelfDefinetion"></bean>
测试代码:
public class ApplicationRun {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("classpath:applicationContext.xml");
//这里其实获取的是 selfMapper的代理对象了
/**
* 证实了,我们往beanDefinitionMap里面自已注册一个bean定义,spring会去根据该bean定义创建对应的信息
*/
SelfMapper selfMapper = (SelfMapper) context.getBean("selfMapper");
System.out.println(selfMapper.selectUser());
}
}
测试结果:
end!!所以spring的生命周期是真的很重要,mybaits与spring的整合就是完完全全的用到了这些东西,继续加油学习吧!准备看一下spring的事务底层是怎么做的!