• Mybatis源码学习二


    Mybatis执行一条查询语句的顺序代码:

      1.入口就是配置类中的@MapperScan注解:

     1 //
     2 // Source code recreated from a .class file by IntelliJ IDEA
     3 // (powered by Fernflower decompiler)
     4 //
     5 
     6 package org.mybatis.spring.annotation;
     7 
     8 import java.lang.annotation.Annotation;
     9 import java.lang.annotation.Documented;
    10 import java.lang.annotation.ElementType;
    11 import java.lang.annotation.Retention;
    12 import java.lang.annotation.RetentionPolicy;
    13 import java.lang.annotation.Target;
    14 import org.mybatis.spring.mapper.MapperFactoryBean;
    15 import org.springframework.beans.factory.support.BeanNameGenerator;
    16 import org.springframework.context.annotation.Import;
    17 
    18 @Retention(RetentionPolicy.RUNTIME)
    19 @Target({ElementType.TYPE})
    20 @Documented
    21 @Import({MapperScannerRegistrar.class})
    22 public @interface MapperScan {
    23     String[] value() default {};
    24 
    25     String[] basePackages() default {};
    26 
    27     Class<?>[] basePackageClasses() default {};
    28 
    29     Class<? extends BeanNameGenerator> nameGenerator() default BeanNameGenerator.class;
    30 
    31     Class<? extends Annotation> annotationClass() default Annotation.class;
    32 
    33     Class<?> markerInterface() default Class.class;
    34 
    35     String sqlSessionTemplateRef() default "";
    36 
    37     String sqlSessionFactoryRef() default "";
    38 
    39     Class<? extends MapperFactoryBean> factoryBean() default MapperFactoryBean.class;
    40 }

      2.进入@Import注解中的MapperScannerRegistrar类

     1 //
     2 // Source code recreated from a .class file by IntelliJ IDEA
     3 // (powered by Fernflower decompiler)
     4 //
     5 
     6 package org.mybatis.spring.annotation;
     7 
     8 import java.lang.annotation.Annotation;
     9 import java.util.ArrayList;
    10 import java.util.List;
    11 import org.mybatis.spring.mapper.ClassPathMapperScanner;
    12 import org.mybatis.spring.mapper.MapperFactoryBean;
    13 import org.springframework.beans.BeanUtils;
    14 import org.springframework.beans.factory.support.BeanDefinitionRegistry;
    15 import org.springframework.beans.factory.support.BeanNameGenerator;
    16 import org.springframework.context.ResourceLoaderAware;
    17 import org.springframework.context.annotation.ImportBeanDefinitionRegistrar;
    18 import org.springframework.core.annotation.AnnotationAttributes;
    19 import org.springframework.core.io.ResourceLoader;
    20 import org.springframework.core.type.AnnotationMetadata;
    21 import org.springframework.util.ClassUtils;
    22 import org.springframework.util.StringUtils;
    23 
    24 public class MapperScannerRegistrar implements ImportBeanDefinitionRegistrar, ResourceLoaderAware {
    25     private ResourceLoader resourceLoader;
    26 
    27     public MapperScannerRegistrar() {
    28     }
    29 
    30     public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
    31         AnnotationAttributes annoAttrs = AnnotationAttributes.fromMap(importingClassMetadata.getAnnotationAttributes(MapperScan.class.getName()));
    32         ClassPathMapperScanner scanner = new ClassPathMapperScanner(registry);
    33         if (this.resourceLoader != null) {
    34             scanner.setResourceLoader(this.resourceLoader);
    35         }
    36 
    37         Class<? extends Annotation> annotationClass = annoAttrs.getClass("annotationClass");
    38         if (!Annotation.class.equals(annotationClass)) {
    39             scanner.setAnnotationClass(annotationClass);
    40         }
    41 
    42         Class<?> markerInterface = annoAttrs.getClass("markerInterface");
    43         if (!Class.class.equals(markerInterface)) {
    44             scanner.setMarkerInterface(markerInterface);
    45         }
    46 
    47         Class<? extends BeanNameGenerator> generatorClass = annoAttrs.getClass("nameGenerator");
    48         if (!BeanNameGenerator.class.equals(generatorClass)) {
    49             scanner.setBeanNameGenerator((BeanNameGenerator)BeanUtils.instantiateClass(generatorClass));
    50         }
    51 
    52         Class<? extends MapperFactoryBean> mapperFactoryBeanClass = annoAttrs.getClass("factoryBean");
    53         if (!MapperFactoryBean.class.equals(mapperFactoryBeanClass)) {
    54             scanner.setMapperFactoryBean((MapperFactoryBean)BeanUtils.instantiateClass(mapperFactoryBeanClass));
    55         }
    56 
    57         scanner.setSqlSessionTemplateBeanName(annoAttrs.getString("sqlSessionTemplateRef"));
    58         scanner.setSqlSessionFactoryBeanName(annoAttrs.getString("sqlSessionFactoryRef"));
    59         List<String> basePackages = new ArrayList();
    60         String[] var10 = annoAttrs.getStringArray("value");
    61         int var11 = var10.length;
    62 
    63         int var12;
    64         String pkg;
    65         for(var12 = 0; var12 < var11; ++var12) {
    66             pkg = var10[var12];
    67             if (StringUtils.hasText(pkg)) {
    68                 basePackages.add(pkg);
    69             }
    70         }
    71 
    72         var10 = annoAttrs.getStringArray("basePackages");
    73         var11 = var10.length;
    74 
    75         for(var12 = 0; var12 < var11; ++var12) {
    76             pkg = var10[var12];
    77             if (StringUtils.hasText(pkg)) {
    78                 basePackages.add(pkg);
    79             }
    80         }
    81 
    82         Class[] var14 = annoAttrs.getClassArray("basePackageClasses");
    83         var11 = var14.length;
    84 
    85         for(var12 = 0; var12 < var11; ++var12) {
    86             Class<?> clazz = var14[var12];
    87             basePackages.add(ClassUtils.getPackageName(clazz));
    88         }
    89 
    90         scanner.registerFilters();
    91         scanner.doScan(StringUtils.toStringArray(basePackages));
    92     }
    93 
    94     public void setResourceLoader(ResourceLoader resourceLoader) {
    95         this.resourceLoader = resourceLoader;
    96     }
    97 }

      3.进入MapperFactoryBean类中的getObject()方法。

     1 //
     2 // Source code recreated from a .class file by IntelliJ IDEA
     3 // (powered by Fernflower decompiler)
     4 //
     5 
     6 package org.mybatis.spring.mapper;
     7 
     8 import org.apache.ibatis.executor.ErrorContext;
     9 import org.apache.ibatis.session.Configuration;
    10 import org.mybatis.spring.support.SqlSessionDaoSupport;
    11 import org.springframework.beans.factory.FactoryBean;
    12 import org.springframework.util.Assert;
    13 
    14 public class MapperFactoryBean<T> extends SqlSessionDaoSupport implements FactoryBean<T> {
    15     private Class<T> mapperInterface;
    16     private boolean addToConfig = true;
    17 
    18     public MapperFactoryBean() {
    19     }
    20 
    21     public MapperFactoryBean(Class<T> mapperInterface) {
    22         this.mapperInterface = mapperInterface;
    23     }
    24 
    25     protected void checkDaoConfig() {
    26         super.checkDaoConfig();
    27         Assert.notNull(this.mapperInterface, "Property 'mapperInterface' is required");
    28         Configuration configuration = this.getSqlSession().getConfiguration();
    29         if (this.addToConfig && !configuration.hasMapper(this.mapperInterface)) {
    30             try {
    31                 configuration.addMapper(this.mapperInterface);
    32             } catch (Exception var6) {
    33                 this.logger.error("Error while adding the mapper '" + this.mapperInterface + "' to configuration.", var6);
    34                 throw new IllegalArgumentException(var6);
    35             } finally {
    36                 ErrorContext.instance().reset();
    37             }
    38         }
    39 
    40     }
    41 
    42     public T getObject() throws Exception {
    43         return this.getSqlSession().getMapper(this.mapperInterface);
    44     }
    45 
    46     public Class<T> getObjectType() {
    47         return this.mapperInterface;
    48     }
    49 
    50     public boolean isSingleton() {
    51         return true;
    52     }
    53 
    54     public void setMapperInterface(Class<T> mapperInterface) {
    55         this.mapperInterface = mapperInterface;
    56     }
    57 
    58     public Class<T> getMapperInterface() {
    59         return this.mapperInterface;
    60     }
    61 
    62     public void setAddToConfig(boolean addToConfig) {
    63         this.addToConfig = addToConfig;
    64     }
    65 
    66     public boolean isAddToConfig() {
    67         return this.addToConfig;
    68     }
    69 }

      4.getObject()方法中的getMapper()接口方法的具体实现:

        如果是Mybatis与Spring想结合的时候,调用的是在SqlSessionTemplate类中的,所以进入SqlSessionTemplate类中的getMapper(Class<T> type)方法。

        如果是Mybatis自己运行的时候,调用的是DefaultSqlSessio类中的。

      1 //
      2 // Source code recreated from a .class file by IntelliJ IDEA
      3 // (powered by Fernflower decompiler)
      4 //
      5 
      6 package org.mybatis.spring;
      7 
      8 import java.lang.reflect.InvocationHandler;
      9 import java.lang.reflect.Method;
     10 import java.lang.reflect.Proxy;
     11 import java.sql.Connection;
     12 import java.util.List;
     13 import java.util.Map;
     14 import org.apache.ibatis.cursor.Cursor;
     15 import org.apache.ibatis.exceptions.PersistenceException;
     16 import org.apache.ibatis.executor.BatchResult;
     17 import org.apache.ibatis.reflection.ExceptionUtil;
     18 import org.apache.ibatis.session.Configuration;
     19 import org.apache.ibatis.session.ExecutorType;
     20 import org.apache.ibatis.session.ResultHandler;
     21 import org.apache.ibatis.session.RowBounds;
     22 import org.apache.ibatis.session.SqlSession;
     23 import org.apache.ibatis.session.SqlSessionFactory;
     24 import org.springframework.beans.factory.DisposableBean;
     25 import org.springframework.dao.support.PersistenceExceptionTranslator;
     26 import org.springframework.util.Assert;
     27 
     28 public class SqlSessionTemplate implements SqlSession, DisposableBean {
     29     private final SqlSessionFactory sqlSessionFactory;
     30     private final ExecutorType executorType;
     31     private final SqlSession sqlSessionProxy;
     32     private final PersistenceExceptionTranslator exceptionTranslator;
     33 
     34     public SqlSessionTemplate(SqlSessionFactory sqlSessionFactory) {
     35         this(sqlSessionFactory, sqlSessionFactory.getConfiguration().getDefaultExecutorType());
     36     }
     37 
     38     public SqlSessionTemplate(SqlSessionFactory sqlSessionFactory, ExecutorType executorType) {
     39         this(sqlSessionFactory, executorType, new MyBatisExceptionTranslator(sqlSessionFactory.getConfiguration().getEnvironment().getDataSource(), true));
     40     }
     41 
     42     public SqlSessionTemplate(SqlSessionFactory sqlSessionFactory, ExecutorType executorType, PersistenceExceptionTranslator exceptionTranslator) {
     43         Assert.notNull(sqlSessionFactory, "Property 'sqlSessionFactory' is required");
     44         Assert.notNull(executorType, "Property 'executorType' is required");
     45         this.sqlSessionFactory = sqlSessionFactory;
     46         this.executorType = executorType;
     47         this.exceptionTranslator = exceptionTranslator;
     48         this.sqlSessionProxy = (SqlSession)Proxy.newProxyInstance(SqlSessionFactory.class.getClassLoader(), new Class[]{SqlSession.class}, new SqlSessionTemplate.SqlSessionInterceptor());
     49     }
     50 
     51     public SqlSessionFactory getSqlSessionFactory() {
     52         return this.sqlSessionFactory;
     53     }
     54 
     55     public ExecutorType getExecutorType() {
     56         return this.executorType;
     57     }
     58 
     59     public PersistenceExceptionTranslator getPersistenceExceptionTranslator() {
     60         return this.exceptionTranslator;
     61     }
     62 
     63     public <T> T selectOne(String statement) {
     64         return this.sqlSessionProxy.selectOne(statement);
     65     }
     66 
     67     public <T> T selectOne(String statement, Object parameter) {
     68         return this.sqlSessionProxy.selectOne(statement, parameter);
     69     }
     70 
     71     public <K, V> Map<K, V> selectMap(String statement, String mapKey) {
     72         return this.sqlSessionProxy.selectMap(statement, mapKey);
     73     }
     74 
     75     public <K, V> Map<K, V> selectMap(String statement, Object parameter, String mapKey) {
     76         return this.sqlSessionProxy.selectMap(statement, parameter, mapKey);
     77     }
     78 
     79     public <K, V> Map<K, V> selectMap(String statement, Object parameter, String mapKey, RowBounds rowBounds) {
     80         return this.sqlSessionProxy.selectMap(statement, parameter, mapKey, rowBounds);
     81     }
     82 
     83     public <T> Cursor<T> selectCursor(String statement) {
     84         return this.sqlSessionProxy.selectCursor(statement);
     85     }
     86 
     87     public <T> Cursor<T> selectCursor(String statement, Object parameter) {
     88         return this.sqlSessionProxy.selectCursor(statement, parameter);
     89     }
     90 
     91     public <T> Cursor<T> selectCursor(String statement, Object parameter, RowBounds rowBounds) {
     92         return this.sqlSessionProxy.selectCursor(statement, parameter, rowBounds);
     93     }
     94 
     95     public <E> List<E> selectList(String statement) {
     96         return this.sqlSessionProxy.selectList(statement);
     97     }
     98 
     99     public <E> List<E> selectList(String statement, Object parameter) {
    100         return this.sqlSessionProxy.selectList(statement, parameter);
    101     }
    102 
    103     public <E> List<E> selectList(String statement, Object parameter, RowBounds rowBounds) {
    104         return this.sqlSessionProxy.selectList(statement, parameter, rowBounds);
    105     }
    106 
    107     public void select(String statement, ResultHandler handler) {
    108         this.sqlSessionProxy.select(statement, handler);
    109     }
    110 
    111     public void select(String statement, Object parameter, ResultHandler handler) {
    112         this.sqlSessionProxy.select(statement, parameter, handler);
    113     }
    114 
    115     public void select(String statement, Object parameter, RowBounds rowBounds, ResultHandler handler) {
    116         this.sqlSessionProxy.select(statement, parameter, rowBounds, handler);
    117     }
    118 
    119     public int insert(String statement) {
    120         return this.sqlSessionProxy.insert(statement);
    121     }
    122 
    123     public int insert(String statement, Object parameter) {
    124         return this.sqlSessionProxy.insert(statement, parameter);
    125     }
    126 
    127     public int update(String statement) {
    128         return this.sqlSessionProxy.update(statement);
    129     }
    130 
    131     public int update(String statement, Object parameter) {
    132         return this.sqlSessionProxy.update(statement, parameter);
    133     }
    134 
    135     public int delete(String statement) {
    136         return this.sqlSessionProxy.delete(statement);
    137     }
    138 
    139     public int delete(String statement, Object parameter) {
    140         return this.sqlSessionProxy.delete(statement, parameter);
    141     }
    142 
    143     public <T> T getMapper(Class<T> type) {
    144         return this.getConfiguration().getMapper(type, this);
    145     }
    146 
    147     public void commit() {
    148         throw new UnsupportedOperationException("Manual commit is not allowed over a Spring managed SqlSession");
    149     }
    150 
    151     public void commit(boolean force) {
    152         throw new UnsupportedOperationException("Manual commit is not allowed over a Spring managed SqlSession");
    153     }
    154 
    155     public void rollback() {
    156         throw new UnsupportedOperationException("Manual rollback is not allowed over a Spring managed SqlSession");
    157     }
    158 
    159     public void rollback(boolean force) {
    160         throw new UnsupportedOperationException("Manual rollback is not allowed over a Spring managed SqlSession");
    161     }
    162 
    163     public void close() {
    164         throw new UnsupportedOperationException("Manual close is not allowed over a Spring managed SqlSession");
    165     }
    166 
    167     public void clearCache() {
    168         this.sqlSessionProxy.clearCache();
    169     }
    170 
    171     public Configuration getConfiguration() {
    172         return this.sqlSessionFactory.getConfiguration();
    173     }
    174 
    175     public Connection getConnection() {
    176         return this.sqlSessionProxy.getConnection();
    177     }
    178 
    179     public List<BatchResult> flushStatements() {
    180         return this.sqlSessionProxy.flushStatements();
    181     }
    182 
    183     public void destroy() throws Exception {
    184     }
    185 
    186     private class SqlSessionInterceptor implements InvocationHandler {
    187         private SqlSessionInterceptor() {
    188         }
    189 
    190         public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
    191             SqlSession sqlSession = SqlSessionUtils.getSqlSession(SqlSessionTemplate.this.sqlSessionFactory, SqlSessionTemplate.this.executorType, SqlSessionTemplate.this.exceptionTranslator);
    192 
    193             Object unwrapped;
    194             try {
    195                 Object result = method.invoke(sqlSession, args);
    196                 if (!SqlSessionUtils.isSqlSessionTransactional(sqlSession, SqlSessionTemplate.this.sqlSessionFactory)) {
    197                     sqlSession.commit(true);
    198                 }
    199 
    200                 unwrapped = result;
    201             } catch (Throwable var11) {
    202                 unwrapped = ExceptionUtil.unwrapThrowable(var11);
    203                 if (SqlSessionTemplate.this.exceptionTranslator != null && unwrapped instanceof PersistenceException) {
    204                     SqlSessionUtils.closeSqlSession(sqlSession, SqlSessionTemplate.this.sqlSessionFactory);
    205                     sqlSession = null;
    206                     Throwable translated = SqlSessionTemplate.this.exceptionTranslator.translateExceptionIfPossible((PersistenceException)unwrapped);
    207                     if (translated != null) {
    208                         unwrapped = translated;
    209                     }
    210                 }
    211 
    212                 throw (Throwable)unwrapped;
    213             } finally {
    214                 if (sqlSession != null) {
    215                     SqlSessionUtils.closeSqlSession(sqlSession, SqlSessionTemplate.this.sqlSessionFactory);
    216                 }
    217 
    218             }
    219 
    220             return unwrapped;
    221         }
    222     }
    223 }

      5.进入getMapper()方法的实现类MapperRegistry类中。

     1 //
     2 // Source code recreated from a .class file by IntelliJ IDEA
     3 // (powered by Fernflower decompiler)
     4 //
     5 
     6 package org.apache.ibatis.binding;
     7 
     8 import java.util.Collection;
     9 import java.util.Collections;
    10 import java.util.HashMap;
    11 import java.util.Iterator;
    12 import java.util.Map;
    13 import java.util.Set;
    14 import org.apache.ibatis.builder.annotation.MapperAnnotationBuilder;
    15 import org.apache.ibatis.io.ResolverUtil;
    16 import org.apache.ibatis.io.ResolverUtil.IsA;
    17 import org.apache.ibatis.session.Configuration;
    18 import org.apache.ibatis.session.SqlSession;
    19 
    20 public class MapperRegistry {
    21     private final Configuration config;
    22     private final Map<Class<?>, MapperProxyFactory<?>> knownMappers = new HashMap();
    23 
    24     public MapperRegistry(Configuration config) {
    25         this.config = config;
    26     }
    27 
    28     public <T> T getMapper(Class<T> type, SqlSession sqlSession) {
    29         MapperProxyFactory<T> mapperProxyFactory = (MapperProxyFactory)this.knownMappers.get(type);
    30         if (mapperProxyFactory == null) {
    31             throw new BindingException("Type " + type + " is not known to the MapperRegistry.");
    32         } else {
    33             try {
    34                 return mapperProxyFactory.newInstance(sqlSession);
    35             } catch (Exception var5) {
    36                 throw new BindingException("Error getting mapper instance. Cause: " + var5, var5);
    37             }
    38         }
    39     }
    40 
    41     public <T> boolean hasMapper(Class<T> type) {
    42         return this.knownMappers.containsKey(type);
    43     }
    44 
    45     public <T> void addMapper(Class<T> type) {
    46         if (type.isInterface()) {
    47             if (this.hasMapper(type)) {
    48                 throw new BindingException("Type " + type + " is already known to the MapperRegistry.");
    49             }
    50 
    51             boolean loadCompleted = false;
    52 
    53             try {
    54                 this.knownMappers.put(type, new MapperProxyFactory(type));
    55                 MapperAnnotationBuilder parser = new MapperAnnotationBuilder(this.config, type);
    56                 parser.parse();
    57                 loadCompleted = true;
    58             } finally {
    59                 if (!loadCompleted) {
    60                     this.knownMappers.remove(type);
    61                 }
    62 
    63             }
    64         }
    65 
    66     }
    67 
    68     public Collection<Class<?>> getMappers() {
    69         return Collections.unmodifiableCollection(this.knownMappers.keySet());
    70     }
    71 
    72     public void addMappers(String packageName, Class<?> superType) {
    73         ResolverUtil<Class<?>> resolverUtil = new ResolverUtil();
    74         resolverUtil.find(new IsA(superType), packageName);
    75         Set<Class<? extends Class<?>>> mapperSet = resolverUtil.getClasses();
    76         Iterator var5 = mapperSet.iterator();
    77 
    78         while(var5.hasNext()) {
    79             Class<?> mapperClass = (Class)var5.next();
    80             this.addMapper(mapperClass);
    81         }
    82 
    83     }
    84 
    85     public void addMappers(String packageName) {
    86         this.addMappers(packageName, Object.class);
    87     }
    88 }

      6.查看方法得知这个方法主要处理的是一个Mapper的代理工厂,进入MapperProxyFactory。

     1 //
     2 // Source code recreated from a .class file by IntelliJ IDEA
     3 // (powered by Fernflower decompiler)
     4 //
     5 
     6 package org.apache.ibatis.binding;
     7 
     8 import java.lang.reflect.Method;
     9 import java.lang.reflect.Proxy;
    10 import java.util.Map;
    11 import java.util.concurrent.ConcurrentHashMap;
    12 import org.apache.ibatis.session.SqlSession;
    13 
    14 public class MapperProxyFactory<T> {
    15     private final Class<T> mapperInterface;
    16     private final Map<Method, MapperMethod> methodCache = new ConcurrentHashMap();
    17 
    18     public MapperProxyFactory(Class<T> mapperInterface) {
    19         this.mapperInterface = mapperInterface;
    20     }
    21 
    22     public Class<T> getMapperInterface() {
    23         return this.mapperInterface;
    24     }
    25 
    26     public Map<Method, MapperMethod> getMethodCache() {
    27         return this.methodCache;
    28     }
    29 
    30     protected T newInstance(MapperProxy<T> mapperProxy) {
    31         return Proxy.newProxyInstance(this.mapperInterface.getClassLoader(), new Class[]{this.mapperInterface}, mapperProxy);
    32     }
    33 
    34     public T newInstance(SqlSession sqlSession) {
    35         MapperProxy<T> mapperProxy = new MapperProxy(sqlSession, this.mapperInterface, this.methodCache);
    36         return this.newInstance(mapperProxy);
    37     }
    38 }

      6.代理工厂MapperProxyFactory中产生的是MapperProxy类:

     1 //
     2 // Source code recreated from a .class file by IntelliJ IDEA
     3 // (powered by Fernflower decompiler)
     4 //
     5 
     6 package org.apache.ibatis.binding;
     7 
     8 import java.io.Serializable;
     9 import java.lang.invoke.MethodHandles;
    10 import java.lang.invoke.MethodType;
    11 import java.lang.invoke.MethodHandles.Lookup;
    12 import java.lang.reflect.Constructor;
    13 import java.lang.reflect.InvocationHandler;
    14 import java.lang.reflect.Method;
    15 import java.util.Map;
    16 import org.apache.ibatis.reflection.ExceptionUtil;
    17 import org.apache.ibatis.session.SqlSession;
    18 
    19 public class MapperProxy<T> implements InvocationHandler, Serializable {
    20     private static final long serialVersionUID = -6424540398559729838L;
    21     private static final int ALLOWED_MODES = 15;
    22     private static final Constructor<Lookup> lookupConstructor;
    23     private static final Method privateLookupInMethod;
    24     private final SqlSession sqlSession;
    25     private final Class<T> mapperInterface;
    26     private final Map<Method, MapperMethod> methodCache;
    27 
    28     public MapperProxy(SqlSession sqlSession, Class<T> mapperInterface, Map<Method, MapperMethod> methodCache) {
    29         this.sqlSession = sqlSession;
    30         this.mapperInterface = mapperInterface;
    31         this.methodCache = methodCache;
    32     }
    33 
    34     public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
    35         try {
    36             if (Object.class.equals(method.getDeclaringClass())) {
    37                 return method.invoke(this, args);
    38             }
    39 
    40             if (method.isDefault()) {
    41                 if (privateLookupInMethod == null) {
    42                     return this.invokeDefaultMethodJava8(proxy, method, args);
    43                 }
    44 
    45                 return this.invokeDefaultMethodJava9(proxy, method, args);
    46             }
    47         } catch (Throwable var5) {
    48             throw ExceptionUtil.unwrapThrowable(var5);
    49         }
    50 
    51         MapperMethod mapperMethod = this.cachedMapperMethod(method);
    52         return mapperMethod.execute(this.sqlSession, args);
    53     }
    54 
    55     private MapperMethod cachedMapperMethod(Method method) {
    56         return (MapperMethod)this.methodCache.computeIfAbsent(method, (k) -> {
    57             return new MapperMethod(this.mapperInterface, method, this.sqlSession.getConfiguration());
    58         });
    59     }
    60 
    61     private Object invokeDefaultMethodJava9(Object proxy, Method method, Object[] args) throws Throwable {
    62         Class<?> declaringClass = method.getDeclaringClass();
    63         return ((Lookup)privateLookupInMethod.invoke((Object)null, declaringClass, MethodHandles.lookup())).findSpecial(declaringClass, method.getName(), MethodType.methodType(method.getReturnType(), method.getParameterTypes()), declaringClass).bindTo(proxy).invokeWithArguments(args);
    64     }
    65 
    66     private Object invokeDefaultMethodJava8(Object proxy, Method method, Object[] args) throws Throwable {
    67         Class<?> declaringClass = method.getDeclaringClass();
    68         return ((Lookup)lookupConstructor.newInstance(declaringClass, 15)).unreflectSpecial(method, declaringClass).bindTo(proxy).invokeWithArguments(args);
    69     }
    70 
    71     static {
    72         Method privateLookupIn;
    73         try {
    74             privateLookupIn = MethodHandles.class.getMethod("privateLookupIn", Class.class, Lookup.class);
    75         } catch (NoSuchMethodException var5) {
    76             privateLookupIn = null;
    77         }
    78 
    79         privateLookupInMethod = privateLookupIn;
    80         Constructor<Lookup> lookup = null;
    81         if (privateLookupInMethod == null) {
    82             try {
    83                 lookup = Lookup.class.getDeclaredConstructor(Class.class, Integer.TYPE);
    84                 lookup.setAccessible(true);
    85             } catch (NoSuchMethodException var3) {
    86                 throw new IllegalStateException("There is neither 'privateLookupIn(Class, Lookup)' nor 'Lookup(Class, int)' method in java.lang.invoke.MethodHandles.", var3);
    87             } catch (Throwable var4) {
    88                 lookup = null;
    89             }
    90         }
    91 
    92         lookupConstructor = lookup;
    93     }
    94 }

      7.由于是代理方法,所以实现逻辑的部分是在这个invoke()方法中:

     1 public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
     2         try {
     3             if (Object.class.equals(method.getDeclaringClass())) {
     4                 return method.invoke(this, args);
     5             }
     6 
     7             if (method.isDefault()) {
     8                 if (privateLookupInMethod == null) {
     9                     return this.invokeDefaultMethodJava8(proxy, method, args);
    10                 }
    11 
    12                 return this.invokeDefaultMethodJava9(proxy, method, args);
    13             }
    14         } catch (Throwable var5) {
    15             throw ExceptionUtil.unwrapThrowable(var5);
    16         }
    17 
    18         MapperMethod mapperMethod = this.cachedMapperMethod(method);
    19         return mapperMethod.execute(this.sqlSession, args);
    20     }

    Mybatis与Spring结合的时候是怎么进行初始化的?

      实现spring提供的一个InitializingBean接口,这个接口中的afterPropertiesSet()方法进行初始化。

      在Mybatis中的MapperFactoryBean继承了SqlSessionDaoSupport,而SqlSessionDaoSupport继承自DaoSupport,DaoSupport实现了InitializingBean接口。

     1 //
     2 // Source code recreated from a .class file by IntelliJ IDEA
     3 // (powered by Fernflower decompiler)
     4 //
     5 
     6 package org.mybatis.spring.mapper;
     7 
     8 import org.apache.ibatis.executor.ErrorContext;
     9 import org.apache.ibatis.session.Configuration;
    10 import org.mybatis.spring.support.SqlSessionDaoSupport;
    11 import org.springframework.beans.factory.FactoryBean;
    12 import org.springframework.util.Assert;
    13 
    14 public class MapperFactoryBean<T> extends SqlSessionDaoSupport implements FactoryBean<T> {
    15     private Class<T> mapperInterface;
    16     private boolean addToConfig = true;
    17 
    18     public MapperFactoryBean() {
    19     }
    20 
    21     public MapperFactoryBean(Class<T> mapperInterface) {
    22         this.mapperInterface = mapperInterface;
    23     }
    24 
    25     protected void checkDaoConfig() {
    26         super.checkDaoConfig();
    27         Assert.notNull(this.mapperInterface, "Property 'mapperInterface' is required");
    28         Configuration configuration = this.getSqlSession().getConfiguration();
    29         if (this.addToConfig && !configuration.hasMapper(this.mapperInterface)) {
    30             try {
    31                 configuration.addMapper(this.mapperInterface);
    32             } catch (Exception var6) {
    33                 this.logger.error("Error while adding the mapper '" + this.mapperInterface + "' to configuration.", var6);
    34                 throw new IllegalArgumentException(var6);
    35             } finally {
    36                 ErrorContext.instance().reset();
    37             }
    38         }
    39 
    40     }
    41 
    42     public T getObject() throws Exception {
    43         return this.getSqlSession().getMapper(this.mapperInterface);
    44     }
    45 
    46     public Class<T> getObjectType() {
    47         return this.mapperInterface;
    48     }
    49 
    50     public boolean isSingleton() {
    51         return true;
    52     }
    53 
    54     public void setMapperInterface(Class<T> mapperInterface) {
    55         this.mapperInterface = mapperInterface;
    56     }
    57 
    58     public Class<T> getMapperInterface() {
    59         return this.mapperInterface;
    60     }
    61 
    62     public void setAddToConfig(boolean addToConfig) {
    63         this.addToConfig = addToConfig;
    64     }
    65 
    66     public boolean isAddToConfig() {
    67         return this.addToConfig;
    68     }
    69 }
     1 //
     2 // Source code recreated from a .class file by IntelliJ IDEA
     3 // (powered by Fernflower decompiler)
     4 //
     5 
     6 package org.mybatis.spring.support;
     7 
     8 import org.apache.ibatis.session.SqlSession;
     9 import org.apache.ibatis.session.SqlSessionFactory;
    10 import org.mybatis.spring.SqlSessionTemplate;
    11 import org.springframework.dao.support.DaoSupport;
    12 import org.springframework.util.Assert;
    13 
    14 public abstract class SqlSessionDaoSupport extends DaoSupport {
    15     private SqlSession sqlSession;
    16     private boolean externalSqlSession;
    17 
    18     public SqlSessionDaoSupport() {
    19     }
    20 
    21     public void setSqlSessionFactory(SqlSessionFactory sqlSessionFactory) {
    22         if (!this.externalSqlSession) {
    23             this.sqlSession = new SqlSessionTemplate(sqlSessionFactory);
    24         }
    25 
    26     }
    27 
    28     public void setSqlSessionTemplate(SqlSessionTemplate sqlSessionTemplate) {
    29         this.sqlSession = sqlSessionTemplate;
    30         this.externalSqlSession = true;
    31     }
    32 
    33     public SqlSession getSqlSession() {
    34         return this.sqlSession;
    35     }
    36 
    37     protected void checkDaoConfig() {
    38         Assert.notNull(this.sqlSession, "Property 'sqlSessionFactory' or 'sqlSessionTemplate' are required");
    39     }
    40 }
     1 //
     2 // Source code recreated from a .class file by IntelliJ IDEA
     3 // (powered by Fernflower decompiler)
     4 //
     5 
     6 package org.springframework.dao.support;
     7 
     8 import org.apache.commons.logging.Log;
     9 import org.apache.commons.logging.LogFactory;
    10 import org.springframework.beans.factory.BeanInitializationException;
    11 import org.springframework.beans.factory.InitializingBean;
    12 
    13 public abstract class DaoSupport implements InitializingBean {
    14     protected final Log logger = LogFactory.getLog(this.getClass());
    15 
    16     public DaoSupport() {
    17     }
    18 
    19     public final void afterPropertiesSet() throws IllegalArgumentException, BeanInitializationException {
    20         this.checkDaoConfig();
    21 
    22         try {
    23             this.initDao();
    24         } catch (Exception var2) {
    25             throw new BeanInitializationException("Initialization of DAO failed", var2);
    26         }
    27     }
    28 
    29     protected abstract void checkDaoConfig() throws IllegalArgumentException;
    30 
    31     protected void initDao() throws Exception {
    32     }
    33 }
     1 //
     2 // Source code recreated from a .class file by IntelliJ IDEA
     3 // (powered by Fernflower decompiler)
     4 //
     5 
     6 package org.springframework.beans.factory;
     7 
     8 public interface InitializingBean {
     9     void afterPropertiesSet() throws Exception;
    10 }
     
  • 相关阅读:
    如何去重一个Oracle表
    配置Eclipse来开发Java 程序
    在windows上使用opera mini
    Oracle OLAP 介绍
    一个Batch作业调度系统构思
    how to Use Subversion with TortoiseSVN
    java official Design Pattern
    how to install ubuntu OS combined with Windows
    确保DWBI项目成功的几个关键点
    spinner 读取sqlite
  • 原文地址:https://www.cnblogs.com/wk-missQ1/p/12635432.html
Copyright © 2020-2023  润新知