|
我们使用Mapper 的时候,只需要在加了Service 注解的类里面使用@Autowired注入Mapper 接口就好了。
@Service
public class EmployeeService {
@Autowired
EmployeeMapper employeeMapper;
public List<Employee> getAll() {
return employeeMapper.selectByMap(null);
}
}
Spring 在启动的时候需要去实例化EmployeeService。
EmployeeService 依赖了EmployeeMapper 接口(是EmployeeService 的一个属性)。
Spring 会根据Mapper 的名字从BeanFactory 中获取它的BeanDefination,再从BeanDefination 中获取BeanClass , EmployeeMapper 对应的BeanClass 是MapperFactoryBean(上一步已经分析过)。
接下来就是创建MapperFactoryBean,因为实现了FactoryBean 接口,同样是调用getObject()方法。
// MapperFactoryBean.java
public T getObject() throws Exception {
return getSqlSession().getMapper(this.mapperInterface);
}
因为MapperFactoryBean 继承了SqlSessionDaoSupport , 所以这个getSqlSession()就是调用父类的方法,返回SqlSessionTemplate。
// SqlSessionDaoSupport.java
public SqlSession getSqlSession() {
return this.sqlSessionTemplate;
}
第二步,SqlSessionTemplate 的getMapper()方法,里面又有两个方法:
// SqlSessionTemplate.java
public <T> T getMapper(Class<T> type) {
return getConfiguration().getMapper(type, this);
}
第一步:SqlSessionTemplate 的getConfiguration()方法:
// SqlSessionTemplate.java
public Configuration getConfiguration() {
return this.sqlSessionFactory.getConfiguration();
}
进入方法,通过DefaultSqlSessionFactory,返回全部配置Configuration:
// DefaultSqlSessionFactory.java
public Configuration getConfiguration() {
return configuration;
}
第二步:Configuration 的getMapper()方法:
// Configuration.java
public <T> T getMapper(Class<T> type, SqlSession sqlSession) {
return mapperRegistry.getMapper(type, sqlSession);
}
这一步我们很熟悉, 跟编程式使用里面的getMapper 一样, 通过工厂类MapperProxyFactory 获得一个MapperProxy 代理对象。
也就是说,我们注入到Service 层的接口,实际上还是一个MapperProxy 代理对象。所以最后调用Mapper 接口的方法,也是执行MapperProxy 的invoke()方法,后面的流程就跟编程式的工程里面一模一样了。
总结:
| 对象 | 生命周期 | | SqlSessionTemplate | Spring 中SqlSession 的替代品,是线程安全的,通过代理的方式调用 DefaultSqlSession 的方法 | | SqlSessionInterceptor(内部类) | 代理对象,用来代理DefaultSqlSession,在SqlSessionTemplate 中使用 | | SqlSessionDaoSupport | 用于获取SqlSessionTemplate,只要继承它即可 | | MapperFactoryBean | 注册到IOC 容器中替换接口类,继承了SqlSessionDaoSupport 用来获取 SqlSessionTemplate,因为注入接口的时候,就会调用它的getObject()方法 | | SqlSessionHolder | 控制SqlSession 和事务 |
思考:@MapperScan 注解是怎么解析的?
|