• *
  • trace
  • *
  • warn
  • *
  • *

    通过自己定义的接口来实现各大日志框架的内容达到高可用

  • * @author Clinton Begin
  • */
  • public interface Log {
  • boolean isDebugEnabled();
  • boolean isTraceEnabled();
  • void error(String s, Throwable e);
  • void error(String s);
  • void debug(String s);
  • void trace(String s);
  • void warn(String s);
  • }
  • 有了日志接口必然有实现类,mybatis有log4j2 、 slf4j 等日志的相关实现 , 下面是Slf4j实现的代码,其他代码也是一样的模式进行初始化。

    1. public class Slf4jImpl implements Log {
    2. private Log log;
    3. /**
    4. * 创建日志实例
    5. * @param clazz
    6. */
    7. public Slf4jImpl(String clazz) {
    8. Logger logger = LoggerFactory.getLogger(clazz);
    9. if (logger instanceof LocationAwareLogger) {
    10. try {
    11. // check for slf4j >= 1.6 method signature
    12. logger.getClass().getMethod("log", Marker.class, String.class, int.class, String.class, Object[].class, Throwable.class);
    13. log = new Slf4jLocationAwareLoggerImpl((LocationAwareLogger) logger);
    14. return;
    15. } catch (SecurityException | NoSuchMethodException e) {
    16. // fail-back to Slf4jLoggerImpl
    17. }
    18. }
    19. // Logger is not LocationAwareLogger or slf4j version < 1.6
    20. log = new Slf4jLoggerImpl(logger);
    21. }
    22. @Override
    23. public boolean isDebugEnabled() {
    24. return log.isDebugEnabled();
    25. }
    26. @Override
    27. public boolean isTraceEnabled() {
    28. return log.isTraceEnabled();
    29. }
    30. @Override
    31. public void error(String s, Throwable e) {
    32. log.error(s, e);
    33. }
    34. @Override
    35. public void error(String s) {
    36. log.error(s);
    37. }
    38. @Override
    39. public void debug(String s) {
    40. log.debug(s);
    41. }
    42. @Override
    43. public void trace(String s) {
    44. log.trace(s);
    45. }
    46. @Override
    47. public void warn(String s) {
    48. log.warn(s);
    49. }
    50. }

    通过上述方法来达到统一接口多个实现,这个在开发中也经常使用.多日志的实现方法有了还缺一个创建方法,创建方法由org.apache.ibatis.logging.LogFactory提供

    1. /**
    2. *

      日志工厂,实现内容:

    3. *
      1. *
      2. org.slf4j.Logger 日志框架 slf4j
      3. *
      4. org.apache.commons.logging.Log 日志框架 apache
      5. *
      6. org.apache.logging.log4j.Logger 日志框架 log4j2
      7. *
      8. org.apache.log4j.Logger 日志框架 log4j
      9. *
      10. java.util.logging.Logger 日志框架,JDK的logger
      11. *
      12. *
    4. * @author Clinton Begin
    5. * @author Eduardo Macarron
    6. */
    7. public final class LogFactory {
    8. /**
    9. * Marker to be used by logging implementations that support markers.
    10. */
    11. public static final String MARKER = "MYBATIS";
    12. private static Constructorextends Log> logConstructor;
    13. /**
    14. * 日志的实现类的具体选择
    15. */
    16. static {
    17. // slf4j 日志
    18. tryImplementation(LogFactory::useSlf4jLogging);
    19. // apache 日志
    20. tryImplementation(LogFactory::useCommonsLogging);
    21. // log4j2 日志
    22. tryImplementation(LogFactory::useLog4J2Logging);
    23. // log4 日志
    24. tryImplementation(LogFactory::useLog4JLogging);
    25. // JDK 日志
    26. tryImplementation(LogFactory::useJdkLogging);
    27. // 空 日志
    28. tryImplementation(LogFactory::useNoLogging);
    29. }
    30. /**
    31. * 私有化构造方法,这是一个单例
    32. */
    33. private LogFactory() {
    34. // disable construction
    35. }
    36. public static Log getLog(Class aClass) {
    37. return getLog(aClass.getName());
    38. }
    39. public static Log getLog(String logger) {
    40. try {
    41. return logConstructor.newInstance(logger);
    42. } catch (Throwable t) {
    43. throw new LogException("Error creating logger for logger " + logger + ". Cause: " + t, t);
    44. }
    45. }
    46. public static synchronized void useCustomLogging(Class clazz) {
    47. setImplementation(clazz);
    48. }
    49. public static synchronized void useSlf4jLogging() {
    50. setImplementation(org.apache.ibatis.logging.slf4j.Slf4jImpl.class);
    51. }
    52. public static synchronized void useCommonsLogging() {
    53. setImplementation(org.apache.ibatis.logging.commons.JakartaCommonsLoggingImpl.class);
    54. }
    55. public static synchronized void useLog4JLogging() {
    56. setImplementation(org.apache.ibatis.logging.log4j.Log4jImpl.class);
    57. }
    58. public static synchronized void useLog4J2Logging() {
    59. setImplementation(org.apache.ibatis.logging.log4j2.Log4j2Impl.class);
    60. }
    61. public static synchronized void useJdkLogging() {
    62. setImplementation(org.apache.ibatis.logging.jdk14.Jdk14LoggingImpl.class);
    63. }
    64. public static synchronized void useStdOutLogging() {
    65. setImplementation(org.apache.ibatis.logging.stdout.StdOutImpl.class);
    66. }
    67. public static synchronized void useNoLogging() {
    68. setImplementation(org.apache.ibatis.logging.nologging.NoLoggingImpl.class);
    69. }
    70. /**
    71. * 选择具体的日志实现
    72. */
    73. private static void tryImplementation(Runnable runnable) {
    74. if (logConstructor == null) {
    75. try {
    76. // run()? 似乎违背了代码的语义, 看静态方法.静态方法多行同类型的操作我认为是一个多线程
    77. runnable.run();
    78. } catch (Throwable t) {
    79. // ignore
    80. }
    81. }
    82. }
    83. /**
    84. * 选择具体的日志实现
    85. */
    86. private static void setImplementation(Class implClass) {
    87. try {
    88. Constructorextends Log> candidate = implClass.getConstructor(String.class);
    89. Log log = candidate.newInstance(LogFactory.class.getName());
    90. if (log.isDebugEnabled()) {
    91. log.debug("Logging initialized using '" + implClass + "' adapter.");
    92. }
    93. logConstructor = candidate;
    94. } catch (Throwable t) {
    95. throw new LogException("Error setting Log implementation. Cause: " + t, t);
    96. }
    97. }
    98. }
    99. LogFactory是一个单例对象,对外公开getLog方法在使用时直接private static final Log log = LogFactory.getLog(CglibProxyFactory.class);即可

      在 org.apache.ibatis.session.Configuration 中可以看到下面这些注册方法

      1. // 日志实现类
      2. typeAliasRegistry.registerAlias("SLF4J", Slf4jImpl.class);
      3. typeAliasRegistry.registerAlias("COMMONS_LOGGING", JakartaCommonsLoggingImpl.class);
      4. typeAliasRegistry.registerAlias("LOG4J", Log4jImpl.class);
      5. typeAliasRegistry.registerAlias("LOG4J2", Log4j2Impl.class);
      6. typeAliasRegistry.registerAlias("JDK_LOGGING", Jdk14LoggingImpl.class);
      7. typeAliasRegistry.registerAlias("STDOUT_LOGGING", StdOutImpl.class);
      8. typeAliasRegistry.registerAlias("NO_LOGGING", NoLoggingImpl.class);

      mybatis反射

      mybatis 的反射相关内容在org.apache.ibatis.reflection 下存放。主要讲解org.apache.ibatis.reflection.Reflector类,先看一下该类的属性

      1. public class Reflector {
      2. /**
      3. * 实体类.class
      4. */
      5. private final Class type;
      6. /**
      7. * 可读 属性
      8. */
      9. private final String[] readablePropertyNames;
      10. /**
      11. * 可写 属性值
      12. */
      13. private final String[] writablePropertyNames;
      14. /**
      15. * set 方法列表
      16. */
      17. private final Map setMethods = new HashMap<>();
      18. /**
      19. * get 方法列表
      20. */
      21. private final Map getMethods = new HashMap<>();
      22. /**
      23. * set 的数据类型
      24. */
      25. private final Map> setTypes = new HashMap<>();
      26. /**
      27. * get 的数据类型
      28. */
      29. private final Map> getTypes = new HashMap<>();
      30. /**
      31. * 构造函数
      32. */
      33. private Constructor defaultConstructor;
      34. /**
      35. * 缓存数据, 大写KEY
      36. */
      37. private Map caseInsensitivePropertyMap = new HashMap<>();
      38. }

      构造方法, 构造方法传入一个类的字节码,在构造方法中设置相关的属性值

      1. public class Reflector {
      2. /**
      3. * @param clazz 待解析类的字节码
      4. */
      5. public Reflector(Class clazz) {
      6. type = clazz;
      7. // 构造方法
      8. addDefaultConstructor(clazz);
      9. // get 方法
      10. addGetMethods(clazz);
      11. // set 方法
      12. addSetMethods(clazz);
      13. // 字段值
      14. addFields(clazz);
      15. readablePropertyNames = getMethods.keySet().toArray(new String[0]);
      16. writablePropertyNames = setMethods.keySet().toArray(new String[0]);
      17. for (String propName : readablePropertyNames) {
      18. // 循环操作设置到缓存中,
      19. caseInsensitivePropertyMap.put(propName.toUpperCase(Locale.ENGLISH), propName);
      20. }
      21. for (String propName : writablePropertyNames) {
      22. caseInsensitivePropertyMap.put(propName.toUpperCase(Locale.ENGLISH), propName);
      23. }
      24. }
      25. }

      addDefaultConstructor 方法 

      1. private void addDefaultConstructor(Class clazz) {
      2. // 获取类里面的所有构造方法
      3. Constructor[] constructors = clazz.getDeclaredConstructors();
      4. // 过滤得到空参构造 constructor -> constructor.getParameterTypes().length == 0
      5. Arrays.stream(constructors).filter(constructor -> constructor.getParameterTypes().length == 0)
      6. .findAny().ifPresent(constructor -> {
      7. System.out.println("有空参构造");
      8. this.defaultConstructor = constructor;
      9. });
      10. }

      测试类

      1. public class People {
      2. private String name;
      3. public People() {
      4. }
      5. public People(String name) {
      6. this.name = name;
      7. }
      8. @Override
      9. public String toString() {
      10. return "People{" +
      11. "name='" + name + '\'' +
      12. '}';
      13. }
      14. public String getName() {
      15. return name;
      16. }
      17. public void setName(String name) {
      18. this.name = name;
      19. }
      20. }
      21. import org.junit.jupiter.api.Test;
      22. import java.lang.reflect.Constructor;
      23. class HfReflectorTest {
      24. @Test
      25. void getDefaultConstructorTest() throws Exception {
      26. Reflector reflector = new Reflector(People.class);
      27. // 获取空参构造方法
      28. Constructor defaultConstructor = reflector.getDefaultConstructor();
      29. People o = (People) defaultConstructor.newInstance();
      30. o.setName("hhh");
      31. System.out.println(o);
      32. }
      33. }

      org.apache.ibatis.reflection.Reflector#getDefaultConstructor方法, 该方法是获取构造函数的方法,如果构造函数没有就抛出异常

      1. public Constructor getDefaultConstructor() {
      2. if (defaultConstructor != null) {
      3. return defaultConstructor;
      4. } else {
      5. // 如果没有空参构造抛出的异常
      6. throw new ReflectionException("There is no default constructor for " + type);
      7. }
      8. }

      addGetMethods

      该方法获取了所有getis开头的方法

      1. private void addGetMethods(Class clazz) {
      2. // 反射方法
      3. Map> conflictingGetters = new HashMap<>();
      4. Method[] methods = getClassMethods(clazz);
      5. // JDK8 filter 过滤get 开头的方法
      6. Arrays.stream(methods).filter(m -> m.getParameterTypes().length == 0 && PropertyNamer.isGetter(m.getName()))
      7. .forEach(m -> addMethodConflict(conflictingGetters, PropertyNamer.methodToProperty(m.getName()), m));
      8. resolveGetterConflicts(conflictingGetters);
      9. }

       该方法中依旧使用了 JDK8 语法通过m.getParameterTypes().length == 0 && PropertyNamer.isGetter(m.getName())来判断是否是get或·is开头的内容。调用org.apache.ibatis.reflection.property.PropertyNamer

      1. public static boolean isGetter(String name) {
      2. // 在语义上 is 开头的也是get开头的
      3. return (name.startsWith("get") && name.length() > 3) || (name.startsWith("is") && name.length() > 2);
      4. }

      getClassMethods

      org.apache.ibatis.reflection.Reflector#getClassMethods,该方法将传入对象的所有可见方法都获取到进行唯一标识处理成一个Map对象 添加方法为org.apache.ibatis.reflection.Reflector#addUniqueMethods

      1. private Method[] getClassMethods(Class clazz) {
      2. // 方法唯一标识: 方法
      3. Map uniqueMethods = new HashMap<>();
      4. Class currentClass = clazz;
      5. while (currentClass != null && currentClass != Object.class) {
      6. // getDeclaredMethods 获取 public ,private , protcted 方法
      7. addUniqueMethods(uniqueMethods, currentClass.getDeclaredMethods());
      8. // we also need to look for interface methods -
      9. // because the class may be abstract
      10. // 当前类是否继承别的类(实现接口)如果继承则需要进行操作
      11. Class[] interfaces = currentClass.getInterfaces();
      12. for (Class anInterface : interfaces) {
      13. // getMethods 获取本身和父类的 public 方法
      14. addUniqueMethods(uniqueMethods, anInterface.getMethods());
      15. }
      16. // 循环往上一层一层寻找最后回到 Object 类 的上级为null 结束
      17. currentClass = currentClass.getSuperclass();
      18. }
      19. Collection methods = uniqueMethods.values();
      20. return methods.toArray(new Method[0]);
      21. }

      org.apache.ibatis.reflection.Reflector#addUniqueMethods

      1. private void addUniqueMethods(Map uniqueMethods, Method[] methods) {
      2. for (Method currentMethod : methods) {
      3. // 桥接, 具体还不知道
      4. // TODO: 2019/12/9 JAVA 桥接方法
      5. if (!currentMethod.isBridge()) {
      6. // 方法的唯一标识
      7. String signature = getSignature(currentMethod);
      8. // check to see if the method is already known
      9. // if it is known, then an extended class must have
      10. // overridden a method
      11. if (!uniqueMethods.containsKey(signature)) {
      12. uniqueMethods.put(signature, currentMethod);
      13. }
      14. }
      15. }
      16. }

      唯一标识方法org.apache.ibatis.reflection.Reflector#getSignature

      1. /**
      2. * 方法唯一标识,返回值类型#方法名称:参数列表
      3. *
      4. * @param method
      5. * @return
      6. */
      7. private String getSignature(Method method) {
      8. StringBuilder sb = new StringBuilder();
      9. Class returnType = method.getReturnType();
      10. if (returnType != null) {
      11. sb.append(returnType.getName()).append('#');
      12. }
      13. sb.append(method.getName());
      14. Class[] parameters = method.getParameterTypes();
      15. for (int i = 0; i < parameters.length; i++) {
      16. sb.append(i == 0 ? ':' : ',').append(parameters[i].getName());
      17. }
      18. return sb.toString();
      19. }

      resolveGetterConflicts

      org.apache.ibatis.reflection.Reflector#resolveGetterConflicts

      这个方法解决了get方法的冲突问题,同名方法不同返回值

      1. private void resolveGetterConflicts(Map> conflictingGetters) {
      2. for (Entry> entry : conflictingGetters.entrySet()) {
      3. Method winner = null;
      4. String propName = entry.getKey();
      5. boolean isAmbiguous = false;
      6. for (Method candidate : entry.getValue()) {
      7. if (winner == null) {
      8. winner = candidate;
      9. continue;
      10. }
      11. Class winnerType = winner.getReturnType();
      12. Class candidateType = candidate.getReturnType();
      13. if (candidateType.equals(winnerType)) {
      14. if (!boolean.class.equals(candidateType)) {
      15. isAmbiguous = true;
      16. break;
      17. } else if (candidate.getName().startsWith("is")) {
      18. winner = candidate;
      19. }
      20. } else if (candidateType.isAssignableFrom(winnerType)) {
      21. // OK getter type is descendant
      22. } else if (winnerType.isAssignableFrom(candidateType)) {
      23. winner = candidate;
      24. } else {
      25. isAmbiguous = true;
      26. break;
      27. }
      28. }
      29. addGetMethod(propName, winner, isAmbiguous);
      30. }
      31. }

      addFields

      org.apache.ibatis.reflection.Reflector#addFields

      获取类的所有字段没什么好说的直接递归就可以获取了

      1. private void addFields(Class clazz) {
      2. Field[] fields = clazz.getDeclaredFields();
      3. for (Field field : fields) {
      4. if (!setMethods.containsKey(field.getName())) {
      5. // issue #379 - removed the check for final because JDK 1.5 allows
      6. // modification of final fields through reflection (JSR-133). (JGB)
      7. // pr #16 - final static can only be set by the classloader
      8. int modifiers = field.getModifiers();
      9. if (!(Modifier.isFinal(modifiers) && Modifier.isStatic(modifiers))) {
      10. addSetField(field);
      11. }
      12. }
      13. if (!getMethods.containsKey(field.getName())) {
      14. addGetField(field);
      15. }
      16. }
      17. if (clazz.getSuperclass() != null) {
      18. addFields(clazz.getSuperclass());
      19. }
      20. }

      Mybatis DataSource

      org.apache.ibatis.datasource.DataSourceFactory

      1. /**
      2. * 数据源工厂
      3. * @author Clinton Begin
      4. */
      5. public interface DataSourceFactory {
      6. /**
      7. * 设置 dataSource 属性
      8. * @param props
      9. */
      10. void setProperties(Properties props);
      11. /**
      12. * 获取 dataSource
      13. * @return {@link DataSource}
      14. */
      15. DataSource getDataSource();
      16. }

       setProperties会将下列标签放入datasource

      1. <dataSource type="POOLED">
      2. <property name="driver" value="com.mysql.jdbc.Driver"/>
      3. <property name="url" value="jdbc:mysql://localhost:3306/mybatis?useSSL=false"/>
      4. <property name="username" value="mybatis"/>
      5. <property name="password" value="mybatis"/>
      6. dataSource>

       在org.apache.ibatis.session.Configuration中有配置下面三个信息

      1. typeAliasRegistry.registerAlias("JNDI", JndiDataSourceFactory.class);
      2. typeAliasRegistry.registerAlias("POOLED", PooledDataSourceFactory.class);
      3. typeAliasRegistry.registerAlias("UNPOOLED", UnpooledDataSourceFactory.class);

      JndiDataSourceFactory

      1. /**
      2. * @author Clinton Begin
      3. */
      4. public class JndiDataSourceFactory implements DataSourceFactory {
      5. public static final String INITIAL_CONTEXT = "initial_context";
      6. public static final String DATA_SOURCE = "data_source";
      7. public static final String ENV_PREFIX = "env.";
      8. /**
      9. * 直接 java 数据源
      10. */
      11. private DataSource dataSource;
      12. /**
      13. * 获取数据源的配置信息
      14. * @param allProps
      15. * @return
      16. */
      17. private static Properties getEnvProperties(Properties allProps) {
      18. final String PREFIX = ENV_PREFIX;
      19. Properties contextProperties = null;
      20. for (Entry entry : allProps.entrySet()) {
      21. String key = (String) entry.getKey();
      22. String value = (String) entry.getValue();
      23. // 只获取前缀`env`
      24. if (key.startsWith(PREFIX)) {
      25. if (contextProperties == null) {
      26. contextProperties = new Properties();
      27. }
      28. // 放入数据
      29. contextProperties.put(key.substring(PREFIX.length()), value);
      30. }
      31. }
      32. return contextProperties;
      33. }
      34. /**
      35. * 设置数据源属性
      36. * @param properties
      37. */
      38. @Override
      39. public void setProperties(Properties properties) {
      40. try {
      41. InitialContext initCtx;
      42. Properties env = getEnvProperties(properties);
      43. if (env == null) {
      44. initCtx = new InitialContext();
      45. } else {
      46. initCtx = new InitialContext(env);
      47. }
      48. if (properties.containsKey(INITIAL_CONTEXT)
      49. && properties.containsKey(DATA_SOURCE)) {
      50. // 如果包含`initial_context`和`data_source`
      51. Context ctx = (Context) initCtx.lookup(properties.getProperty(INITIAL_CONTEXT));
      52. dataSource = (DataSource) ctx.lookup(properties.getProperty(DATA_SOURCE));
      53. } else if (properties.containsKey(DATA_SOURCE)) {
      54. dataSource = (DataSource) initCtx.lookup(properties.getProperty(DATA_SOURCE));
      55. }
      56. } catch (NamingException e) {
      57. throw new DataSourceException("There was an error configuring JndiDataSourceTransactionPool. Cause: " + e, e);
      58. }
      59. }
      60. @Override
      61. public DataSource getDataSource() {
      62. return dataSource;
      63. }
      64. }

      PooledDataSource

      1. protected int poolMaximumActiveConnections = 10;
      2. protected int poolMaximumIdleConnections = 5;
      3. protected int poolMaximumCheckoutTime = 20000;
      4. protected int poolTimeToWait = 20000;
      5. protected int poolMaximumLocalBadConnectionTolerance = 3;
      6. protected String poolPingQuery = "NO PING QUERY SET";
      7. protected boolean poolPingEnabled;
      8. protected int poolPingConnectionsNotUsedFor;

      PooledDataSourceFactory

      1. public class PooledDataSourceFactory extends UnpooledDataSourceFactory {
      2. public PooledDataSourceFactory() {
      3. this.dataSource = new PooledDataSource();
      4. }
      5. }
      6. // 初始化
      7. public PooledDataSource() {
      8. dataSource = new UnpooledDataSource();
      9. }

      UnpooledDataSourceFactory

      1. @Override
      2. public void setProperties(Properties properties) {
      3. Properties driverProperties = new Properties();
      4. //metaDataSource 现在是一个dataSource
      5. MetaObject metaDataSource = SystemMetaObject.forObject(dataSource);
      6. for (Object key : properties.keySet()) {
      7. String propertyName = (String) key;
      8. if (propertyName.startsWith(DRIVER_PROPERTY_PREFIX)) {
      9. // 如果是 driver. 前缀开头
      10. String value = properties.getProperty(propertyName);
      11. driverProperties.setProperty(propertyName.substring(DRIVER_PROPERTY_PREFIX_LENGTH), value);
      12. } else if (metaDataSource.hasSetter(propertyName)) {
      13. String value = (String) properties.get(propertyName);
      14. Object convertedValue = convertValue(metaDataSource, propertyName, value);
      15. // 通过 metaDataSource 来对 dataSource 进行设置属性
      16. metaDataSource.setValue(propertyName, convertedValue);
      17. } else {
      18. throw new DataSourceException("Unknown DataSource property: " + propertyName);
      19. }
      20. }
      21. if (driverProperties.size() > 0) {
      22. metaDataSource.setValue("driverProperties", driverProperties);
      23. }
      24. }

      UnpooledDataSource

      org.apache.ibatis.datasource.unpooled.UnpooledDataSource主要定义数据库连接相关的一些属性,以及与数据库的链接对象创建

      1. // 一些配置信息
      2. private ClassLoader driverClassLoader;
      3. private Properties driverProperties;
      4. private String driver;
      5. private String url;
      6. private String username;
      7. private String password;
      8. private Boolean autoCommit;
      9. private Integer defaultTransactionIsolationLevel;
      10. private Integer defaultNetworkTimeout;

      初始化连接对象

      1. /**
      2. * 加载链接驱动 如 mysql 链接驱动
      3. * @throws SQLException
      4. */
      5. private synchronized void initializeDriver() throws SQLException {
      6. if (!registeredDrivers.containsKey(driver)) {
      7. Class driverType;
      8. try {
      9. if (driverClassLoader != null) {
      10. driverType = Class.forName(driver, true, driverClassLoader);
      11. } else {
      12. driverType = Resources.classForName(driver);
      13. }
      14. // DriverManager requires the driver to be loaded via the system ClassLoader.
      15. // http://www.kfu.com/~nsayer/Java/dyn-jdbc.html
      16. Driver driverInstance = (Driver) driverType.getDeclaredConstructor().newInstance();
      17. DriverManager.registerDriver(new DriverProxy(driverInstance));
      18. registeredDrivers.put(driver, driverInstance);
      19. } catch (Exception e) {
      20. throw new SQLException("Error setting driver on UnpooledDataSource. Cause: " + e);
      21. }
      22. }
      23. }

      设置连接对象的属性

      1. /**
      2. * 设置连接对象 , 超时时间,是否自动提交事物
      3. * @param conn
      4. * @throws SQLException
      5. */
      6. private void configureConnection(Connection conn) throws SQLException {
      7. if (defaultNetworkTimeout != null) {
      8. conn.setNetworkTimeout(Executors.newSingleThreadExecutor(), defaultNetworkTimeout);
      9. }
      10. if (autoCommit != null && autoCommit != conn.getAutoCommit()) {
      11. conn.setAutoCommit(autoCommit);
      12. }
      13. if (defaultTransactionIsolationLevel != null) {
      14. conn.setTransactionIsolation(defaultTransactionIsolationLevel);
      15. }
      16. }

      获取连接对象

      1. /**
      2. * 获取链接对象
      3. * @param username
      4. * @param password
      5. * @return
      6. * @throws SQLException
      7. */
      8. private Connection doGetConnection(String username, String password) throws SQLException {
      9. Properties props = new Properties();
      10. if (driverProperties != null) {
      11. props.putAll(driverProperties);
      12. }
      13. if (username != null) {
      14. props.setProperty("user", username);
      15. }
      16. if (password != null) {
      17. props.setProperty("password", password);
      18. }
      19. return doGetConnection(props);
      20. }

      解析流程

      在 xml 解析的过程中会执行DataSourceFactory相关内容

      1. /**
      2. * 解析 dataSourceElement 标签
      3. *
      4. *
      5. *
      6. *
      7. *
      8. *
      9. *
      10. * @param context
      11. * @return
      12. * @throws Exception
      13. */
      14. private DataSourceFactory dataSourceElement(XNode context) throws Exception {
      15. if (context != null) {
      16. String type = context.getStringAttribute("type");
      17. Properties props = context.getChildrenAsProperties();
      18. //org.apache.ibatis.session.Configuration.Configuration()
      19. DataSourceFactory factory = (DataSourceFactory) resolveClass(type).getDeclaredConstructor().newInstance();
      20. // PooledDataSourceFactory -> UnpooledDataSourceFactory
      21. factory.setProperties(props);
      22. return factory;
      23. }
      24. throw new BuilderException("Environment declaration requires a DataSourceFactory.");
      25. }

    100. 相关阅读:
      AI创作教程之 如何在本地 PC 上运行稳定的 Diffusion 2.0 (无代码指南)
      RT-Thread上部署TinyMaix推理框架,使MCU赋予AI能力
      详解 PyTorch 中的 torch.repeat 函数
      神经网络模型复杂度分析
      C语言:动态内存分配(2)
      【Git】Git常用操作命令大全(笔记)
      Redis的持久化机制
      【STM32】入门(十一):初识uCOS-III
      学习Rust第14天:HashMaps
      设计模式-单例模式
    101. 原文地址:https://blog.csdn.net/xing_jian1/article/details/124770369