spring-mybatis 整合分析
spring-mybatis 的整合流程
- 載入配置jar
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-spring</artifactId>
<version>2.0.4</version>
</dependency>
- 配置datasource 和 sqlsessionFactoryBean
@Bean
public SqlSessionFactory sqlSessionFactory() throws Exception {
SqlSessionFactoryBean factoryBean = new SqlSessionFactoryBean();
factoryBean.setDataSource(dataSource());
return factoryBean.getObject();
}
- 創(chuàng)建mapper 接口
public interface UserMapper {
@Select("SELECT * FROM users WHERE id = #{userId}")
User getUser(@Param("userId") String userId);
}
- 將接口注入到容器中
@Bean
public UserMapper userMapper() throws Exception {
SqlSessionTemplate sqlSessionTemplate = new SqlSessionTemplate(sqlSessionFactory());
return sqlSessionTemplate.getMapper(UserMapper.class);
}
- 交給mapperFactory bean 注入到容器
<bean id="userMapper" class="org.mybatis.spring.mapper.MapperFactoryBean">
<property name="mapperInterface" value="org.mybatis.spring.sample.mapper.UserMapper" />
<property name="sqlSessionFactory" ref="sqlSessionFactory" />
</bean>
然后我們就可以像普通的IOC容器中的bean進行調(diào)用;
- 使用mapperScan("")掃描我們接口莫杈,交給spring管理
原理分析
- 接口是如何注入到容器付燥?
我們知道只有將實體類或者抽象類注入到容器,接口是無法注入到容器中尔破。spring-mybatis 是如何將接口注入到容器。
這里很明顯可以通過動態(tài)代理進行浇衬,生成實體類進行注入懒构;
public class MapperProxy<T> implements InvocationHandler, Serializable {
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
if (Object.class.equals(method.getDeclaringClass())) {
return method.invoke(this, args);
} else {
MapperMethod mapperMethod = this.cachedMapperMethod(method);
return mapperMethod.execute(this.sqlSession, args);
}
}
}
- userMapper 接口是通過 MapperFactoryBean注入到bean容器
在 postBeanFactoryProcesser() 改了class為MapperFactoryBean,
在注冊的過程中將@mapperScan掃描的接口改為耘擂,MapperFactoryBean胆剧,將其注冊到容器中;
構(gòu)造函數(shù)任然是原本的構(gòu)造函數(shù)參數(shù)醉冤,然后通過動態(tài)代理在MapperFactoryBean赞赖,實例化userMapper滚朵;
把注入模型改為 by_type, 給父類sqlSession進程set方法賦值,不改為by_name 是為容錯處理前域,避免配錯辕近;
適應(yīng)工廠bean進行注入,可以隱藏配置的代碼匿垄;
sqlSessionFactoryBean,會解析全局配置文件進行緩存移宅;
然后通過動態(tài)代理在MapperFactoryBean 的 getObject()生成代理對象;
- 我沒并沒有配置代理類的注解(@Bean,@Service),也沒有進行掃描椿疗,他是如何注入的漏峰;
我們知道spring將bean注入容器的 可以使用 @Bean,
@service 等 + @ComponentScan(""), 或者 @Import進行注入;
// 通過在注冊器中届榄,構(gòu)造bean定義并通過import導(dǎo)入,spring整合mybatis
@import(value = {ImportBeanDifinitionRegister.class})
可以實現(xiàn)一個bean定義的注冊類浅乔,將需要的bean注冊到容器;
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
if (this.processPropertyPlaceHolders) {
this.processPropertyPlaceHolders();
}
ClassPathMapperScanner scanner = new ClassPathMapperScanner(registry);
scanner.setAddToConfig(this.addToConfig);
scanner.setAnnotationClass(this.annotationClass);
scanner.setMarkerInterface(this.markerInterface);
scanner.setSqlSessionFactory(this.sqlSessionFactory);
scanner.setSqlSessionTemplate(this.sqlSessionTemplate);
scanner.setSqlSessionFactoryBeanName(this.sqlSessionFactoryBeanName);
scanner.setSqlSessionTemplateBeanName(this.sqlSessionTemplateBeanName);
scanner.setResourceLoader(this.applicationContext);
scanner.setBeanNameGenerator(this.nameGenerator);
scanner.registerFilters();
scanner.scan(StringUtils.tokenizeToStringArray(this.basePackage, ",; \t\n"));
}
Spring 中循環(huán)依賴是如何解決铝条?
spring中單利支持循環(huán)依賴靖苇。
怎么關(guān)閉spring的循環(huán)依賴?
spring 在初始化的時候完成依賴注入
singlonObjects cache 單利緩存池 容器
為什么要先get singlonObjects
判斷對象是否在創(chuàng)建中
為什么有三級緩存班缰?