spring mybatis1
getBeanPostProcessors()就是所有的后置处理器,就是拦截器,就是责任链模式。
spring和mybatis的桥梁在于
MybatisAutoConfiguration,MapperFactoryBean
## 数据源配置 spring.datasource.url=jdbc:mysql://localhost:3306/upgrade?useUnicode=true&characterEncoding=utf8 spring.datasource.username=root spring.datasource.password= spring.datasource.driver-class-name=com.mysql.jdbc.Driver ## Mybatis 配置 mybatis.typeAliasesPackage=com.hcxy.car.bean mybatis.mapperLocations=classpath:mapper/*.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>springboot</groupId>
<artifactId>springboot-mybatis</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>springboot-mybatis</name>
<!-- Spring Boot 启动父依赖 -->
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.5.12.RELEASE</version>
</parent>
<properties>
<mybatis-spring-boot>1.2.0</mybatis-spring-boot>
<mysql-connector>5.1.39</mysql-connector>
</properties>
<dependencies>
<!-- Spring Boot Web 依赖 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- Spring Boot Test 依赖 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<!-- Spring Boot Mybatis 依赖 -->
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>${mybatis-spring-boot}</version>
</dependency>
<!-- MySQL 连接驱动依赖 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>${mysql-connector}</version>
</dependency>
</dependencies>
</project>
SpringApplication.run(App.class, args); public static ConfigurableApplicationContext run(Object[] sources, String[] args) { return new SpringApplication(sources).run(args); } public SpringApplication(Object... sources) { initialize(sources); }
private void initialize(Object[] sources) { if (sources != null && sources.length > 0) { this.sources.addAll(Arrays.asList(sources)); } this.webEnvironment = deduceWebEnvironment(); setInitializers((Collection) getSpringFactoriesInstances(ApplicationContextInitializer.class)); setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class)); this.mainApplicationClass = deduceMainApplicationClass(); } private <T> Collection<? extends T> getSpringFactoriesInstances(Class<T> type) { return getSpringFactoriesInstances(type, new Class<?>[] {}); }
private <T> Collection<? extends T> getSpringFactoriesInstances(Class<T> type,Class<?>[] parameterTypes, Object... args) { ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); Set<String> names = new LinkedHashSet<String>(SpringFactoriesLoader.loadFactoryNames(type, classLoader)); List<T> instances = createSpringFactoriesInstances(type, parameterTypes,classLoader, args, names); AnnotationAwareOrderComparator.sort(instances); return instances; }
public static List<String> loadFactoryNames(Class<?> factoryClass, ClassLoader classLoader) { String factoryClassName = factoryClass.getName(); try { Enumeration<URL> urls = (classLoader != null ? classLoader.getResources(FACTORIES_RESOURCE_LOCATION) : ClassLoader.getSystemResources(FACTORIES_RESOURCE_LOCATION)); List<String> result = new ArrayList<String>(); while (urls.hasMoreElements()) { URL url = urls.nextElement(); Properties properties = PropertiesLoaderUtils.loadProperties(new UrlResource(url)); String factoryClassNames = properties.getProperty(factoryClassName); result.addAll(Arrays.asList(StringUtils.commaDelimitedListToStringArray(factoryClassNames))); } return result; } }
解析accountController的时候: protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final Object[] args) {//accountController, Object exposedObject = bean; try { populateBean(beanName, mbd, instanceWrapper); //accountController依赖注入accountMapper if (exposedObject != null) { exposedObject = initializeBean(beanName, exposedObject, mbd); } } return exposedObject; }
protected void populateBean(String beanName, RootBeanDefinition mbd, BeanWrapper bw) { //accountController依赖注入accountMapper if (hasInstAwareBpps || needsDepCheck) { if (hasInstAwareBpps) { for (BeanPostProcessor bp : getBeanPostProcessors()) { if (bp instanceof InstantiationAwareBeanPostProcessor) { pvs = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName); if (pvs == null) { return; } } } } if (needsDepCheck) { checkDependencies(beanName, mbd, filteredPds, pvs); } } applyPropertyValues(beanName, mbd, bw, pvs); }
CommonAnnotationBeanPostProcessor类: public PropertyValues postProcessPropertyValues(PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) { InjectionMetadata metadata = findResourceMetadata(beanName, bean.getClass(), pvs);//com.hcxy.car.mapper.AccountMapper try { metadata.inject(bean, beanName, pvs); } return pvs; }
public void inject(Object target, String beanName, PropertyValues pvs) throws Throwable { if (!elementsToIterate.isEmpty()) { for (InjectedElement element : elementsToIterate) { element.inject(target, beanName, pvs); //mapper.AccountMapper,依赖注入进了AccountController, } } }
protected void inject(Object target, String requestingBeanName, PropertyValues pvs) throws Throwable { if (this.isField) { Field field = (Field) this.member; //private com.hcxy.car.mapper.AccountMapper com.hcxy.car.controller.AccountController.accountMapper ReflectionUtils.makeAccessible(field); field.set(target, getResourceToInject(target, requestingBeanName)); //accountMapper设置到了accountController去了。 } }
CommonAnnotationBeanPostProcessor类: protected Object getResourceToInject(Object target, String requestingBeanName) { return (this.lazyLookup ? buildLazyResourceProxy(this, requestingBeanName) : getResource(this, requestingBeanName)); //this = ResourceElement for private com.hcxy.car.mapper.AccountMapper com.hcxy.car.controller.AccountController.accountMapper,requestingBeanName = accountController } protected Object getResource(LookupElement element, String requestingBeanName) throws BeansException { return autowireResource(this.resourceFactory, element, requestingBeanName); }
protected Object autowireResource(BeanFactory factory, LookupElement element, String requestingBeanName) { else { resource = factory.getBean(name, element.lookupType); //name = accountMapper,lookupType = interface com.hcxy.car.mapper.AccountMapper。 //返回accountMapper的代理:org.apache.ibatis.binding.MapperProxy() autowiredBeanNames = Collections.singleton(name); } if (factory instanceof ConfigurableBeanFactory) { ConfigurableBeanFactory beanFactory = (ConfigurableBeanFactory) factory; for (String autowiredBeanName : autowiredBeanNames) { if (beanFactory.containsBean(autowiredBeanName)) { beanFactory.registerDependentBean(autowiredBeanName, requestingBeanName); //accountMapper加到spring的容器, } } } return resource; //返回MapperProxy }
//创建accountMapper
protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final Object[] args) {//accountMapper, Object exposedObject = bean; try { populateBean(beanName, mbd, instanceWrapper); //beanName = accountMapper,instanceWrapper = org.springframework.beans.BeanWrapperImpl: wrapping object [org.mybatis.spring.mapper.MapperFactoryBean@40bf4386] if (exposedObject != null) { exposedObject = initializeBean(beanName, exposedObject, mbd); //返回MapperFactoryBean,没做什么, } } return exposedObject; }
1。populateBean accountMapper protected void populateBean(String beanName, RootBeanDefinition mbd, BeanWrapper bw) { if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) { autowireByType(beanName, mbd, bw, newPvs); //beanName = accountMapper,mbd = Root bean: class [org.mybatis.spring.mapper.MapperFactoryBean]; [E:\Code\AAAAA\AAAAA\2019326\2\upgradetest\target\classes\com\hcxy\car\mapper\AccountMapper.class] } if (hasInstAwareBpps || needsDepCheck) { PropertyDescriptor[] filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching); // if (hasInstAwareBpps) { for (BeanPostProcessor bp : getBeanPostProcessors()) { if (bp instanceof InstantiationAwareBeanPostProcessor) { InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp; pvs = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName); if (pvs == null) { return; } } } } } applyPropertyValues(beanName, mbd, bw, pvs); //beanName = accountMapper,pvs = [bean property 'addToConfig', bean property 'sqlSessionFactory', bean property 'sqlSessionTemplate'] }
1。1,accountMapper解析依赖注入sqlSessionFactory,sqlSessionTemplate
protected void autowireByType( String beanName, AbstractBeanDefinition mbd, BeanWrapper bw, MutablePropertyValues pvs) { TypeConverter converter = getCustomTypeConverter(); //org.springframework.beans.BeanWrapperImpl: wrapping object [org.mybatis.spring.mapper.MapperFactoryBean@40bf4386] Set<String> autowiredBeanNames = new LinkedHashSet<String>(4); String[] propertyNames = unsatisfiedNonSimpleProperties(mbd, bw);//sqlSessionFactory,sqlSessionTemplate for (String propertyName : propertyNames) {//sqlSessionFactory,sqlSessionTemplate try { PropertyDescriptor pd = bw.getPropertyDescriptor(propertyName); //org.springframework.beans.GenericTypeAwarePropertyDescriptor[name=sqlSessionFactory],org.springframework.beans.GenericTypeAwarePropertyDescriptor[name=sqlSessionTemplate] if (Object.class != pd.getPropertyType()) { MethodParameter methodParam = BeanUtils.getWriteMethodParameter(pd); //method 'setSqlSessionFactory' boolean eager = !PriorityOrdered.class.isAssignableFrom(bw.getWrappedClass()); DependencyDescriptor desc = new AutowireByTypeDependencyDescriptor(methodParam, eager); //method 'setSqlSessionFactory' ,method 'setSqlSessionTemplate' parameter 0, Object autowiredArgument = resolveDependency(desc, beanName, autowiredBeanNames, converter); //返回DefaultSqlSessionFactory, SqlSessionTemplate, if (autowiredArgument != null) { pvs.add(propertyName, autowiredArgument); //pvs = [bean property 'addToConfig', bean property 'sqlSessionFactory', bean property 'sqlSessionTemplate'] } } } } }
accountMapper解析依赖注入sqlSessionFactory,sqlSessionTemplate
public Object resolveDependency(DependencyDescriptor descriptor, String requestingBeanName, Set<String> autowiredBeanNames, TypeConverter typeConverter) throws BeansException { else { if (result == null) { result = doResolveDependency(descriptor, requestingBeanName, autowiredBeanNames, typeConverter); //DefaultSqlSessionFactory, } return result; } }
public Object doResolveDependency(DependencyDescriptor descriptor, String beanName, Set<String> autowiredBeanNames, TypeConverter typeConverter) throws BeansException { try { Class<?> type = descriptor.getDependencyType(); //interface org.apache.ibatis.session.SqlSessionFactory Object value = getAutowireCandidateResolver().getSuggestedValue(descriptor); //null Map<String, Object> matchingBeans = findAutowireCandidates(beanName, type, descriptor); //{@9038} sqlSessionFactory -> {@7048} "interface org.apache.ibatis.session.SqlSessionFactory" else { Map.Entry<String, Object> entry = matchingBeans.entrySet().iterator().next(); autowiredBeanName = entry.getKey();//sqlSessionFactory instanceCandidate = entry.getValue();//interface org.apache.ibatis.session.SqlSessionFactory } if (autowiredBeanNames != null) { autowiredBeanNames.add(autowiredBeanName); //sqlSessionFactory } return (instanceCandidate instanceof Class ? descriptor.resolveCandidate(autowiredBeanName, type, this) : instanceCandidate); //sqlSessionFactory,interface org.apache.ibatis.session.SqlSessionFactory, } finally { ConstructorResolver.setCurrentInjectionPoint(previousInjectionPoint); } }
public Object resolveCandidate(String beanName, Class<?> requiredType, BeanFactory beanFactory) { return beanFactory.getBean(beanName, requiredType); //sqlSessionFactory,interface org.apache.ibatis.session.SqlSessionFactory, }
获取SqlSessionFactory的实例。
protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final Object[] args) { //sqlSessionFactory,factoryBeanName=org.mybatis.spring.boot.autoconfigure.MybatisAutoConfiguration; factoryMethodName=sqlSessionFactory;[org/mybatis/spring/boot/autoconfigure/MybatisAutoConfiguration.class] BeanWrapper instanceWrapper = null; if (mbd.isSingleton()) { instanceWrapper = this.factoryBeanInstanceCache.remove(beanName); } if (instanceWrapper == null) { instanceWrapper = createBeanInstance(beanName, mbd, args); //org.springframework.beans.BeanWrapperImpl: wrapping object [org.apache.ibatis.session.defaults.DefaultSqlSessionFactory@21e5f0b6]。 //返回DefaultSqlSessionFactory。 } Object exposedObject = bean; try { populateBean(beanName, mbd, instanceWrapper); //sqlSessionFactory,没做什么 if (exposedObject != null) { exposedObject = initializeBean(beanName, exposedObject, mbd); //没做什么 } } return exposedObject; }
1。1。1 ,createBeanInstance sqlSessionFactory protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, Object[] args) { if (mbd.getFactoryMethodName() != null) { //sqlSessionFactory return instantiateUsingFactoryMethod(beanName, mbd, args); // factoryBeanName=org.mybatis.spring.boot.autoconfigure.MybatisAutoConfiguration; factoryMethodName=sqlSessionFactory; [org/mybatis/spring/boot/autoconfigure/MybatisAutoConfiguration.class]。 //返回DefaultSqlSessionFactory。 } }
protected BeanWrapper instantiateUsingFactoryMethod(String beanName, RootBeanDefinition mbd, Object[] explicitArgs) { return new ConstructorResolver(this).instantiateUsingFactoryMethod(beanName, mbd, explicitArgs); //beanName = sqlSessionFactory,返回DefaultSqlSessionFactory。 }
public BeanWrapper instantiateUsingFactoryMethod( final String beanName, final RootBeanDefinition mbd, final Object[] explicitArgs) { //beanName = sqlSessionFactory, String factoryBeanName = mbd.getFactoryBeanName(); //MybatisAutoConfiguration if (factoryBeanName != null) { factoryBean = this.beanFactory.getBean(factoryBeanName); //开始获取MybatisAutoConfiguration,创建sqlSessionFactory时候获取MybatisAutoConfiguration,返回class MybatisAutoConfiguration$$EnhancerBySpringCGLIB$$bb43e1a8。创建MybatisAutoConfiguration的时候createBeanInstance方法中直接走return autowireConstructor(beanName, mbd, ctors, args);方法返回,会去getBean(“MybatisProperties”)等, factoryClass = factoryBean.getClass();//class MybatisAutoConfiguration$$EnhancerBySpringCGLIB$$bb43e1a8 isStatic = false; } if (factoryMethodToUse == null || argsToUse == null) { factoryClass = ClassUtils.getUserClass(factoryClass); //class org.mybatis.spring.boot.autoconfigure.MybatisAutoConfiguration Method[] candidates = candidateSet.toArray(new Method[candidateSet.size()]); //public SqlSessionFactory MybatisAutoConfiguration.sqlSessionFactory(javax.sql.DataSource) for (Method candidate : candidates) { //public SqlSessionFactory MybatisAutoConfiguration.sqlSessionFactory(javax.sql.DataSource) if (paramTypes.length >= minNrOfArgs) { if (resolvedValues != null) { try { argsHolder = createArgumentArray( beanName, mbd, resolvedValues, bw, paramTypes, paramNames, candidate, autowiring); //里面会去getBean("dataSource"),getBean("dataSource")里面会去getBean(“jdbc.DataSourceConfiguration$Tomcat”),又会去getBean("jdbc.DataSourceProperties"),又会去getBean("dataSourceInitializer"),又会去getBean("jdbc.DataSourceAutoConfiguration"), } } } } } try { else { beanInstance = this.beanFactory.getInstantiationStrategy().instantiate( mbd, beanName, this.beanFactory, factoryBean, factoryMethodToUse, argsToUse); //调用MybatisAutoConfiguration的sqlSessionFactory方法,返回DefaultSqlSessionFactory。 } bw.setBeanInstance(beanInstance); return bw; //返回DefaultSqlSessionFactory。 } }
factoryBean = this.beanFactory.getBean(factoryBeanName); //创建sqlSessionFactory时候创建MybatisAutoConfiguration, protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final Object[] args) { //MybatisAutoConfiguration instanceWrapper = createBeanInstance(beanName, mbd, args);//依赖注入MybatisProperties try { populateBean(beanName, mbd, instanceWrapper); //没有做什么 if (exposedObject != null) { exposedObject = initializeBean(beanName, exposedObject, mbd); //没有做什么 } } } return exposedObject; }
MybatisAutoConfiguration的sqlSessionFactory方法,
public SqlSessionFactory sqlSessionFactory(DataSource dataSource) throws Exception { SqlSessionFactoryBean factory = new SqlSessionFactoryBean(); factory.setDataSource(dataSource); if (StringUtils.hasLength(this.properties.getTypeAliasesPackage())) { factory.setTypeAliasesPackage(this.properties.getTypeAliasesPackage()); //com.hcxy.car.bean } if (!ObjectUtils.isEmpty(this.properties.resolveMapperLocations())) { factory.setMapperLocations(this.properties.resolveMapperLocations()); //file [E:\Code\AAAAA\AAAAA\2019326\2\upgradetest\target\classes\mapper\AccountMapper.xml] } return factory.getObject(); //DefaultSqlSessionFactory, }
SqlSessionFactoryBean的getObject():此时就进到mybatis的解析。 public SqlSessionFactory getObject() throws Exception { if (this.sqlSessionFactory == null) { afterPropertiesSet(); } return this.sqlSessionFactory; }
public void afterPropertiesSet() throws Exception { this.sqlSessionFactory = buildSqlSessionFactory(); //DefautSqlSessionFactory }
protected SqlSessionFactory buildSqlSessionFactory() throws IOException { if (hasLength(this.typeAliasesPackage)) { String[] typeAliasPackageArray = tokenizeToStringArray(this.typeAliasesPackage, ConfigurableApplicationContext.CONFIG_LOCATION_DELIMITERS); //com.hcxy.car.bean } if (this.transactionFactory == null) { this.transactionFactory = new SpringManagedTransactionFactory(); } if (!isEmpty(this.mapperLocations)) { for (Resource mapperLocation : this.mapperLocations) { if (mapperLocation == null) { //file [E:\Code\AAAAA\AAAAA\2019326\2\upgradetest\target\classes\mapper\AccountMapper.xml] continue; } try { XMLMapperBuilder xmlMapperBuilder = new XMLMapperBuilder(mapperLocation.getInputStream(), configuration, mapperLocation.toString(), configuration.getSqlFragments()); xmlMapperBuilder.parse(); } } } return this.sqlSessionFactoryBuilder.build(configuration); //configuration里面解析了接口AccountMapper和AccountMapper.xml文件,[namespace:com.hcxy.car.mapper.AccountMapper, interface com.hcxy.car.mapper.AccountMapper, file [E:\Code\AAAAA\AAAAA\2019326\2\upgradetest\target\classes\mapper\AccountMapper.xml]] }
public XMLMapperBuilder(InputStream inputStream, Configuration configuration, String resource, Map<String, XNode> sqlFragments) { this(new XPathParser(inputStream, true, configuration.getVariables(), new XMLMapperEntityResolver()), configuration, resource, sqlFragments); } public XPathParser(InputStream inputStream, boolean validation, Properties variables, EntityResolver entityResolver) { commonConstructor(validation, variables, entityResolver); this.document = createDocument(new InputSource(inputStream)); //file [E:\Code\AAAAA\AAAAA\2019326\2\upgradetest\target\classes\mapper\AccountMapper.xml] }
public void parse() { if (!configuration.isResourceLoaded(resource)) { configurationElement(parser.evalNode("/mapper")); //获取mapper标签, configuration.addLoadedResource(resource); //resource = file [E:\Code\AAAAA\AAAAA\2019326\2\upgradetest\target\classes\mapper\AccountMapper.xml] bindMapperForNamespace(); } }
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<mapper namespace="com.hcxy.car.mapper.AccountMapper">
<resultMap id="BaseResultMap" type="account">
<id column="id" property="id" jdbcType="INTEGER" />
<result column="name" property="name" jdbcType="INTEGER" />
</resultMap>
<select id="findAll" resultMap="BaseResultMap">
select ac.id ,ac.name
from aa ac
</select>
</mapper>
private void configurationElement(XNode context) { try { String namespace = context.getStringAttribute("namespace"); //com.hcxy.car.mapper.AccountMapper builderAssistant.setCurrentNamespace(namespace); cacheRefElement(context.evalNode("cache-ref")); cacheElement(context.evalNode("cache")); parameterMapElement(context.evalNodes("/mapper/parameterMap")); resultMapElements(context.evalNodes("/mapper/resultMap")); //解析resultMap标签, sqlElement(context.evalNodes("/mapper/sql")); buildStatementFromContext(context.evalNodes("select|insert|update|delete")); //解析select标签, }
private void bindMapperForNamespace() { String namespace = builderAssistant.getCurrentNamespace(); //com.hcxy.car.mapper.AccountMapper if (namespace != null) { Class<?> boundType = null; try { boundType = Resources.classForName(namespace); //interface com.hcxy.car.mapper.AccountMapper } if (boundType != null) { if (!configuration.hasMapper(boundType)) { configuration.addLoadedResource("namespace:" + namespace); configuration.addMapper(boundType); } } } }
public SqlSessionFactory build(Configuration config) { return new DefaultSqlSessionFactory(config); }
accountMapper解析依赖注入 ,sqlSessionTemplate
public Object resolveDependency(DependencyDescriptor descriptor, String requestingBeanName, Set<String> autowiredBeanNames, TypeConverter typeConverter) throws BeansException { else { if (result == null) { result = doResolveDependency(descriptor, requestingBeanName, autowiredBeanNames, typeConverter); //method 'setSqlSessionTemplate' parameter 0, } return result;//返回SqlSessionTemplate。 } }
return (instanceCandidate instanceof Class ? descriptor.resolveCandidate(autowiredBeanName, type, this) : instanceCandidate);
public Object resolveCandidate(String beanName, Class<?> requiredType, BeanFactory beanFactory) { return beanFactory.getBean(beanName, requiredType); //获取sqlSessionTemplate实例, }
protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final Object[] args) { //sqlSessionTemplate, if (instanceWrapper == null) { instanceWrapper = createBeanInstance(beanName, mbd, args); //返回SqlSessionTemplate。 } Object exposedObject = bean; try { populateBean(beanName, mbd, instanceWrapper); //没做什么 if (exposedObject != null) { exposedObject = initializeBean(beanName, exposedObject, mbd);//没做什么 } } return exposedObject; }
protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, Object[] args) { if (mbd.getFactoryMethodName() != null) { return instantiateUsingFactoryMethod(beanName, mbd, args); //sqlSessionTemplate } }
public BeanWrapper instantiateUsingFactoryMethod( final String beanName, final RootBeanDefinition mbd, final Object[] explicitArgs) { String factoryBeanName = mbd.getFactoryBeanName(); //MybatisAutoConfiguration, if (factoryBeanName != null) { factoryBean = this.beanFactory.getBean(factoryBeanName); //获取MybatisAutoConfiguration实例,在SqlSessionFactory时候,已经实例化了,这里不用实例化了。 factoryClass = factoryBean.getClass(); //class org.mybatis.spring.boot.autoconfigure.MybatisAutoConfiguration$$EnhancerBySpringCGLIB$$615bec6a isStatic = false; } if (factoryMethodToUse == null || argsToUse == null) { factoryClass = ClassUtils.getUserClass(factoryClass); //class org.mybatis.spring.boot.autoconfigure.MybatisAutoConfiguration AutowireUtils.sortFactoryMethods(candidates); //public SqlSessionTemplate MybatisAutoConfiguration.sqlSessionTemplate(org.apache.ibatis.session.SqlSessionFactory) for (Method candidate : candidates) {//public SqlSessionTemplate MybatisAutoConfiguration.sqlSessionTemplate(org.apache.ibatis.session.SqlSessionFactory) if (paramTypes.length >= minNrOfArgs) { if (resolvedValues != null) { try { argsHolder = createArgumentArray( beanName, mbd, resolvedValues, bw, paramTypes, paramNames, candidate, autowiring);//sqlSessionTemplate,factoryBeanName=MybatisAutoConfiguration; factoryMethodName=sqlSessionTemplate;[org/mybatis/spring/boot/autoconfigure/MybatisAutoConfiguration.class], } } } } } try { else { beanInstance = this.beanFactory.getInstantiationStrategy().instantiate(mbd, beanName, this.beanFactory, factoryBean, factoryMethodToUse, argsToUse); //调用MybatisAutoConfiguration的sqlSessionTemplate方法,返回SqlSessionTemplate。 } bw.setBeanInstance(beanInstance); return bw; } }
调用MybatisAutoConfiguration的sqlSessionTemplate方法,
public SqlSessionTemplate sqlSessionTemplate(SqlSessionFactory sqlSessionFactory) { //sqlSessionFactory = DefaultSqlSessionFactory return executorType != null ? new SqlSessionTemplate(sqlSessionFactory, executorType) : new SqlSessionTemplate(sqlSessionFactory); } public SqlSessionTemplate(SqlSessionFactory sqlSessionFactory) { this(sqlSessionFactory, sqlSessionFactory.getConfiguration().getDefaultExecutorType()); }
protected void applyPropertyValues(String beanName, BeanDefinition mbd, BeanWrapper bw, PropertyValues pvs) { //beanName = accountMapper,pvs = [bean property 'addToConfig', bean property 'sqlSessionFactory', bean property 'sqlSessionTemplate'] else { original = Arrays.asList(pvs.getPropertyValues()); //[bean property 'addToConfig', bean property 'sqlSessionFactory', bean property 'sqlSessionTemplate'] } try { bw.setPropertyValues(new MutablePropertyValues(deepCopy)); //deepCopy = [bean property 'addToConfig', bean property 'sqlSessionFactory', bean property 'sqlSessionTemplate'] ,bw是accountMapper = org.springframework.beans.BeanWrapperImpl: wrapping object [org.mybatis.spring.mapper.MapperFactoryBean@61ab89b0] } }
方法的调用: @RequestMapping(value = "/all", method = RequestMethod.GET) public Map<String, Object> all1(HttpServletRequest request, HttpServletResponse response) { List<Account> l = null; l = accountMapper.findAll(); }; public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { final MapperMethod mapperMethod = cachedMapperMethod(method); return mapperMethod.execute(sqlSession, args); } result = sqlSession.<E>selectList(command.getName(), param); //sqlSession = SqlSessionTemplate
SqlSessionTemplate类: public <E> List<E> selectList(String statement, Object parameter) { return this.sqlSessionProxy.<E> selectList(statement, parameter); //sqlSessionProxy = DefaultSqlSession }
private class SqlSessionInterceptor implements InvocationHandler { @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { SqlSession sqlSession = getSqlSession( SqlSessionTemplate.this.sqlSessionFactory, SqlSessionTemplate.this.executorType, SqlSessionTemplate.this.exceptionTranslator); try { Object result = method.invoke(sqlSession, args); if (!isSqlSessionTransactional(sqlSession, SqlSessionTemplate.this.sqlSessionFactory)) { sqlSession.commit(true); } return result; } finally { if (sqlSession != null) { closeSqlSession(sqlSession, SqlSessionTemplate.this.sqlSessionFactory); } } } }
DefaultSqlSessionFactory类: public SqlSession openSession(ExecutorType execType) { return openSessionFromDataSource(execType, null, false); } DefaultSqlSession类: public <E> List<E> selectList(String statement, Object parameter) { return this.selectList(statement, parameter, RowBounds.DEFAULT); } public <E> List<E> selectList(String statement, Object parameter, RowBounds rowBounds) { try { MappedStatement ms = configuration.getMappedStatement(statement); return executor.query(ms, wrapCollection(parameter), rowBounds, Executor.NO_RESULT_HANDLER); } }
public <E> List<E> query(MappedStatement ms, Object parameterObject, RowBounds rowBounds, ResultHandler resultHandler) throws SQLException { BoundSql boundSql = ms.getBoundSql(parameterObject); CacheKey key = createCacheKey(ms, parameterObject, rowBounds, boundSql); return query(ms, parameterObject, rowBounds, resultHandler, key, boundSql); } return delegate.<E> query(ms, parameterObject, rowBounds, resultHandler, key, boundSql);
populateBean(beanName, mbd, instanceWrapper); //beanName = userMapper 依赖注入userMapper时候还会依赖注入:mybatis-org.mybatis.spring.boot.autoconfigure.MybatisProperties,org.mybatis.spring.boot.autoconfigure.MybatisAutoConfiguration,org.springframework.boot.autoconfigure.jdbc.DataSourceConfiguration$Hikari,spring.datasource-org.springframework.boot.autoconfigure.jdbc.DataSourceProperties,dataSource,org.springframework.boot.autoconfigure.jdbc.DataSourceInitializerInvoker,sqlSessionFactory,sqlSessionTemplate, exposedObject = initializeBean(beanName, exposedObject, mbd); //beanName = userMapper,exposedObject = MapperFactoryBean里面有mapperInterface=interface com.example.mapper.UserMapper,sqlSession=SqlSessionTemplate。SqlSessionTemplate里面有sqlSessionFactory=DefaultSqlSessionFactory。
getBean(userMapper)之后,就要Mapper的生成代理,过程:
if (mbd.isSingleton()) { sharedInstance = getSingleton(beanName, () -> { return createBean(beanName, mbd, args); }); //获取mapper实例,sharedInstance =MapperFactoryBean,里面有mapperInterface=interface com.example.mapper.UserMapper,sqlSession=SqlSessionTemplate。SqlSessionTemplate里面有sqlSessionFactory=DefaultSqlSessionFactory。 bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd); }
protected Object getObjectForBeanInstance(Object beanInstance, String name, String beanName, @Nullable RootBeanDefinition mbd) { if (object == null) { FactoryBean<?> factory = (FactoryBean<?>) beanInstance; //factory = MapperFactoryBean if (mbd == null && containsBeanDefinition(beanName)) { mbd = getMergedLocalBeanDefinition(beanName); } boolean synthetic = (mbd != null && mbd.isSynthetic()); object = getObjectFromFactoryBean(factory, beanName, !synthetic);//factory = MapperFactoryBean,beanName = userMapper。 } return object; }
protected Object getObjectFromFactoryBean(FactoryBean<?> factory, String beanName, boolean shouldPostProcess) { if (factory.isSingleton() && containsSingleton(beanName)) { synchronized (getSingletonMutex()) { Object object = this.factoryBeanObjectCache.get(beanName); if (object == null) { object = doGetObjectFromFactoryBean(factory, beanName); //factory = MapperFactoryBean,beanName = userMapper。 } return object; //返回org.apache.ibatis.binding.MapperProxy(就是动态代理)。 } } }
private Object doGetObjectFromFactoryBean(final FactoryBean<?> factory, final String beanName) { try { else { object = factory.getObject();//factory = MapperFactoryBean ,返回org.apache.ibatis.binding.MapperProxy(就是动态代理)。 } } return object; }
MapperFactoryBean类: public T getObject() throws Exception { return getSqlSession().getMapper(this.mapperInterface); //getSqlSession()返回SqlSessionTemplate, } SqlSessionTemplate类: public <T> T getMapper(Class<T> type) { return getConfiguration().getMapper(type, this); } public <T> T getMapper(Class<T> type, SqlSession sqlSession) { return mapperRegistry.getMapper(type, sqlSession); //type = interface com.example.mapper.UserMapper,sqlSession = SQLSessionTemplate } public <T> T getMapper(Class<T> type, SqlSession sqlSession) { final MapperProxyFactory<T> mapperProxyFactory = (MapperProxyFactory<T>) knownMappers.get(type); //MapperProxyFactory try { return mapperProxyFactory.newInstance(sqlSession); } }
MapperProxyFactory类: public T newInstance(SqlSession sqlSession) { final MapperProxy<T> mapperProxy = new MapperProxy<T>(sqlSession, mapperInterface, methodCache);//SQLSessionTemplate,interface com.example.mapper.UserMapper, return newInstance(mapperProxy); } protected T newInstance(MapperProxy<T> mapperProxy) { return (T) Proxy.newProxyInstance(mapperInterface.getClassLoader(), new Class[] { mapperInterface }, mapperProxy); //jdk的动态代理。 }