聊一聊MyBatis的核心概念、Spring相关的核心内容,主要结合源码理解Spring是如何整合MyBatis的。(结合右侧目录了解吧)
MyBatis相关核心概念粗略回顾 SqlSessionFactory创建SqlSession的工厂
SqlSessionsql请求的会话,通过SqlSessionFactory获取。
String resource = "mybatis-config.xml"; InputStream resourceAsStream = Resources.getResourceAsStream(resource); SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder(); SqlSessionFactory sqlSessionFactory = sqlSessionFactoryBuilder.build(resourceAsStream); // 通过Builder获取构建SqlSessionFactory(读取mybatis-config.xml文件配置) SqlSession sqlSession = sqlSessionFactory.openSession(); // 开启Session UserMapper userMapper = sqlSession.getMapper(UserMapper.class); User user = userMapper.findByUserId(1);上述代码就是单独使用MyBatis的时候的API例子。读取mybatis-config.xml构建出SqlSessionFactory,通过Factory开启SqlSession,使用SqlSession获取Mapper的代理实例。
Mapper public interface UserMapper { User findByUserId(Integer userId); } <mapper namepsace = "com.deepz.mybatis.user.UserMapper"> <select id = "findByUserId" resultType="User"> ... </select> </mapper>以上就是咱们熟悉的MyBatis使用代码了,一个Mapper接口对应的就有一个XML文件。
Spring相关核心概念粗略回顾 FactoryBean接口是一种特殊的SpringBean,对应的真实实例是FactoryBean接口中getObject()方法的返回值,用于自定义复杂的Bean生成。
FactoryBean类型的Bean的获取AbstractBeanFactory#doGetBean
Object sharedInstance = getSingleton(beanName); // 从三级缓存中根据beanName获取SpringBean if (sharedInstance != null && args == null) { // 如果SpringBean不为空则说明命中缓存,直接获取SpringBean实例即可 if (logger.isDebugEnabled()) { if (isSingletonCurrentlyInCreation(beanName)) { logger.debug("Returning eagerly cached instance of singleton bean '" + beanName + "' that is not fully initialized yet - a consequence of a circular reference"); } else { logger.debug("Returning cached instance of singleton bean '" + beanName + "'"); } } bean = getObjectForBeanInstance(sharedInstance, name, beanName, null); // 获取SpringBean真实实例(针对FactoryBean) }AbstractBeanFactory#getObjectForBeanInstance
// Now we have the bean instance, which may be a normal bean or a FactoryBean. // If it's a FactoryBean, we use it to create a bean instance, unless the // caller actually wants a reference to the factory. if (!(beanInstance instanceof FactoryBean) || BeanFactoryUtils.isFactoryDereference(name)) { // 如果不是FactoryBean类型则直接返回 return beanInstance; } // 后续代码针对FactoryBean类型的SpringBean处理 Object object = null; if (mbd == null) { object = getCachedObjectForFactoryBean(beanName); // 从缓存中获取 } if (object == null) { // Return bean instance from factory. FactoryBean<?> factory = (FactoryBean<?>) beanInstance; // Caches object obtained from FactoryBean if it is a singleton. if (mbd == null && containsBeanDefinition(beanName)) { mbd = getMergedLocalBeanDefinition(beanName); } boolean synthetic = (mbd != null && mbd.isSynthetic()); object = getObjectFromFactoryBean(factory, beanName, !synthetic); // 获取FactoryBean真实实例 } return object;FactoryBeanRegistrySupport#doGetObjectFromFactoryBean
FactoryBeanRegistrySupport#getObjectFromFactoryBean最终会调到如下方法,通过FactoryBean的getObject()获取FactoryBean的真实实例
在SpringBean的生命周期中,Bean的初始化环节Spring会调用AbstractAutowireCapableBeanFactory#invokeInitMethods() 回调实现了InitializingBean接口的Bean的InitializingBean#afterPropertiesSet()
关于SpringBean生命周期欢迎移步笔者的相关总结随笔《深入源码理解SpringBean生命周期》
protected void invokeInitMethods(String beanName, final Object bean, RootBeanDefinition mbd) throws Throwable { boolean isInitializingBean = (bean instanceof InitializingBean); // Bean实现了InitializingBean接口 if (isInitializingBean && (mbd == null || !mbd.isExternallyManagedInitMethod("afterPropertiesSet"))) { if (logger.isDebugEnabled()) { logger.debug("Invoking afterPropertiesSet() on bean with name '" + beanName + "'"); } if (System.getSecurityManager() != null) { try { AccessController.doPrivileged(new PrivilegedExceptionAction<Object>() { @Override public Object run() throws Exception { ((InitializingBean) bean).afterPropertiesSet(); return null; } }, getAccessControlContext()); } catch (PrivilegedActionException pae) { throw pae.getException(); } } else { ((InitializingBean) bean).afterPropertiesSet(); // 显式回调InitializingBean的afterPropertiesSet()方法 } } if (mbd != null) { String initMethodName = mbd.getInitMethodName(); if (initMethodName != null && !(isInitializingBean && "afterPropertiesSet".equals(initMethodName)) && !mbd.isExternallyManagedInitMethod(initMethodName)) { invokeCustomInitMethod(beanName, bean, mbd); } } } BeanDefinitionRegistryPostProcessor接口