• spring 整合 mybatis 中数据源的几种配置方式


      因为spring 整合mybatis的过程中, 有好几种整合方式,尤其是数据源那块,经常看到不一样的配置方式,总感觉有点乱,所以今天有空总结下。

      

      一、采用org.mybatis.spring.mapper.MapperScannerConfigurer

      其实逆向工程也是这种方式

      1、数据源配配置文件

     1 <?xml version="1.0" encoding="UTF-8"?>
     2 <beans xmlns="http://www.springframework.org/schema/beans"
     3     xmlns:context="http://www.springframework.org/schema/context" xmlns:p="http://www.springframework.org/schema/p"
     4     xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx"
     5     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
     6     xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
     7     http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd
     8     http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.0.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.0.xsd
     9     http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-4.0.xsd">
    10 
    11     <!-- 加载配置文件 -->
    12     <context:property-placeholder location="classpath:resource/*.properties" />
    13 
    14     <!-- 数据库连接池 -->
    15     <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource"
    16         destroy-method="close">
    17         <property name="driverClassName" value="${jdbc.driver}" />
    18         <property name="url" value="${jdbc.url}" />
    19         <property name="username" value="${jdbc.username}" />
    20         <property name="password" value="${jdbc.password}" />
    21         <property name="maxActive" value="10" />
    22         <property name="minIdle" value="5" />
    23     </bean>
    24     <!-- sqlsessionFactory -->
    25     <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
    26         <property name="configLocation" value="classpath:mybatis/SqlMapConfig.xml"></property>
    27         <property name="dataSource" ref="dataSource"></property>
    28     </bean>
    29 
    30     <!-- 加载mapper代理对象 -->
    31     <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
    32         <property name="basePackage" value="com.jdd.mapper"></property>
    33         <property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"></property>
    34     </bean>
    35 
    36 </beans>

      2、DAO文件

     1 package com.jdd.mapper;
     2 
     3 import com.jdd.pojo.Employee;
     4 import java.util.List;
     5 
     6 public interface EmployeeMapper {
     7 
     8     public Employee getEmployeeById(int id);
     9 
    10     public List<Employee> findAllEmployees();
    11 
    12 }

      3、Mapper.xml 文件

     1 <?xml version="1.0" encoding="UTF-8" ?>
     2 <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
     3 "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
     4 
     5 <mapper namespace="com.jdd.mapper.EmployeeMapper">
     6 
     7     <select id="getEmployeeById" parameterType="int" resultType="com.jdd.pojo.Employee">
     8         <![CDATA[
     9             select * from employee where id = #{id};
    10         ]]>
    11     </select>
    12     
    13     <select id="findAllEmployees" resultType="com.jdd.pojo.Employee">
    14         <![CDATA[
    15             select * from employee where status='1';
    16         ]]>
    17     </select>
    18 
    19     
    20 </mapper>

      这样在service类里就可以直接注入dao接口了

     1 package com.jdd.service.impl;
     2 
     3 import com.jdd.mapper.EmployeeMapper;
     4 import com.jdd.pojo.Employee;
     5 import com.jdd.service.EmployeeService;
     6 import org.springframework.beans.factory.annotation.Autowired;
     7 import org.springframework.stereotype.Service;
     8 import java.util.List;
     9 
    10 @Service("employeeService")
    11 public class EmployeeServiceImpl implements EmployeeService{
    12 
    13     @Autowired
    14     private EmployeeMapper employeeMapper;
    15 
    16     @Override
    17     public Employee getEmployeeById(int id) {
    18         return employeeMapper.getEmployeeById(id);
    19     }
    20 
    21     @Override
    22     public List<Employee> findAllEmployees() {
    23         return employeeMapper.findAllEmployees();
    24     }
    25 
    26 }

      

      二、 采用抽象类org.mybatis.spring.support.SqlSessionDaoSupport, 给它注入 sqlSessionFactory的方式

      1、数据源配置文件

     1 <?xml version="1.0" encoding="UTF-8"?>
     2 <beans xmlns="http://www.springframework.org/schema/beans"
     3     xmlns:context="http://www.springframework.org/schema/context" xmlns:p="http://www.springframework.org/schema/p"
     4     xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx"
     5     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
     6     xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
     7     http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd
     8     http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.0.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.0.xsd
     9     http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-4.0.xsd">
    10 
    11     <!-- 加载配置文件 -->
    12     <context:property-placeholder location="classpath:resource/*.properties" />
    13 
    14     <!-- 数据库连接池 -->
    15     <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource"
    16         destroy-method="close">
    17         <property name="driverClassName" value="${jdbc.driver}" />
    18         <property name="url" value="${jdbc.url}" />
    19         <property name="username" value="${jdbc.username}" />
    20         <property name="password" value="${jdbc.password}" />
    21         <property name="maxActive" value="10" />
    22         <property name="minIdle" value="5" />
    23     </bean>
    24 
    25     
    26     <!-- sqlsessionFactory -->
    27     <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
    28         <property name="configLocation" value="classpath:mybatis/SqlMapConfig.xml"></property>
    29         <property name="dataSource" ref="dataSource"></property>
    30         <property name="mapperLocations" value="classpath:com/jdd/mapper/*.xml"></property>
    31     </bean>
    32     
    34 </beans>

      2、baseDao类

     1 package com.hd.dao;
     2 
     3 import org.apache.ibatis.session.SqlSessionFactory;
     4 import org.mybatis.spring.support.SqlSessionDaoSupport;
     5 import javax.annotation.Resource;
     6 
     7 public abstract class BaseDao extends SqlSessionDaoSupport {
     8 
     9     @Resource
    10     public void setSqlSessionFactory(SqlSessionFactory sqlSessionFactory) {
    11         super.setSqlSessionFactory(sqlSessionFactory);
    12     }
    13 
    14 }

      3、接口 EmployeeDao.java 类

     1 package com.hd.dao;
     2 
     3 import com.hd.pojo.Employee;
     4 
     5 import java.util.List;
     6 
     7 public interface EmployeeDao {
     8 
     9     Employee getEmployeeById(int id);
    10 
    11     List<Employee> findAllEmployees();
    12 
    13 }

      4、dao实现类 EmployeeDaoImpl

     1 package com.hd.dao.impl;
     2 
     3 import com.hd.dao.BaseDao;
     4 import com.hd.dao.EmployeeDao;
     5 import com.hd.pojo.Employee;
     6 import org.springframework.stereotype.Repository;
     7 import java.util.List;
     8 
     9 @Repository("employeeDao")
    10 public class EmployeeDaoImpl extends BaseDao implements EmployeeDao {
    11 
    12     @Override
    13     public Employee getEmployeeById(int id) {
    14         return this.getSqlSession().selectOne("com.jdd.dao.EmployeeDao.getEmployeeById", id);
    15     }
    16 
    17     @Override
    18     public List<Employee> findAllEmployees() {
    19         return this.getSqlSession().selectList("com.jdd.dao.EmployeeDao.findAllEmployees");
    20     }
    21 
    22    
    23 }

      5、这样就可以在service类里注入 employeeDao了

      三、采用 org.mybatis.spring.SqlSessionTemplate 模板类

      1、数据源文件

     1 <?xml version="1.0" encoding="UTF-8"?>
     2 <beans xmlns="http://www.springframework.org/schema/beans"
     3     xmlns:context="http://www.springframework.org/schema/context" xmlns:p="http://www.springframework.org/schema/p"
     4     xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx"
     5     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
     6     xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
     7     http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd
     8     http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.0.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.0.xsd
     9     http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-4.0.xsd">
    10 
    11     <!-- 加载配置文件 -->
    12     <context:property-placeholder location="classpath:resource/*.properties" />
    13 
    14     <!-- 数据库连接池 -->
    15         <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource"
    16         destroy-method="close">
    17         <property name="driverClassName" value="${jdbc.driver}" />
    18         <property name="url" value="${jdbc.url}" />
    19         <property name="username" value="${jdbc.username}" />
    20         <property name="password" value="${jdbc.password}" />
    21         <property name="maxActive" value="10" />
    22         <property name="minIdle" value="5" />
    23     </bean>
    24     
    25     <!-- sqlsessionFactory -->
    26     <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
    27         <property name="configLocation" value="classpath:mybatis/SqlMapConfig.xml"></property>
    28         <property name="dataSource" ref="dataSource"></property>
    29         <property name="mapperLocations" value="classpath:com/jdd/mapper/*.xml"></property>
    30     </bean>
    31 
    32     <bean id="sqlSessionTemplate" class="org.mybatis.spring.SqlSessionTemplate">
    33         <constructor-arg index="0" ref="sqlSessionFactory"/>
    34     </bean>
    35 
    36 </beans>

      2、 basedao.java 类

     1 package com.hd.dao;
     2 
     3 import org.mybatis.spring.SqlSessionTemplate;
     4 import javax.annotation.Resource;
     5 
     6 public abstract class BaseDao {
     7 
     8     public SqlSessionTemplate sqlSessionTemplate;
     9     @Resource
    10     public void setSqlSessionTemplate(SqlSessionTemplate sqlSessionTemplate) {
    11         this.sqlSessionTemplate = sqlSessionTemplate;
    12     }
    13 }

      3、接口 EmployeeDao.java 类

     1 package com.hd.dao;
     2 
     3 import com.hd.pojo.Employee;
     5 import java.util.List;
     6 
     7 public interface EmployeeDao {
     8 
     9     Employee getEmployeeById(int id);
    10 
    11     List<Employee> findAllEmployees();
    12 }

      4、dao实现类 EmployeeDaoImpl

     1 package com.hd.dao.impl;
     2 
     3 import com.hd.dao.BaseDao;
     4 import com.hd.dao.EmployeeDao;
     5 import com.hd.pojo.Employee;
     6 import org.springframework.stereotype.Repository;
     7 import java.util.List;
     8 
     9 @Repository("employeeDao")
    10 public class EmployeeDaoImpl extends BaseDao implements EmployeeDao {
    11 
    12     @Override
    13     public Employee getEmployeeById(int id) {
    14         return sqlSessionTemplate.selectOne("com.jdd.dao.EmployeeDao.getEmployeeById", id);
    15     }
    16 
    17     @Override
    18     public List<Employee> findAllEmployees() {
    19         return sqlSessionTemplate.selectList("com.jdd.dao.EmployeeDao.findAllEmployees");
    20     }
    21 
    22 
    23 }

      5、同样现在也可以在service类里直接注入 employeeDao使用了。

      注:这里basedao的注入比较灵活,也可以注入 SqlSessionFactory, 然后再setter方法里创建 SqlSessionTemplate,如下:

     1 package com.hd.dao;
     2 
     3 import org.apache.ibatis.session.SqlSessionFactory;
     4 import org.mybatis.spring.SqlSessionTemplate;
     5 
     6 import javax.annotation.Resource;
     7 
     8 public abstract class BaseDao {
     9 
    10     public SqlSessionTemplate sqlSessionTemplate;
    11     @Resource
    12     public void setSqlSessionFactory(SqlSessionFactory sqlSessionFactory) {
    13         sqlSessionTemplate = new SqlSessionTemplate(sqlSessionFactory);
    14     }
    15 
    16 }

      

      其实不管是采用 继承SqlSessionDaoSupport类, 注入 sqlSessionFactory的方式, 还是直接注入 SqlSessionTemplate 的方式, 本质上是一样的。

      如果你采用 注入 sqlSessionFactory的方式, 它在底层也是通过sqlSessionFactory 来创建 SqlSessionTemplate ,然后通过其api来操作。

      不信给你们看下 SqlSessionDaoSupport 的源码:

     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 }

      同样 SqlSessionTemplate 继承了 SqlSession 接口, 因此不管操作哪个效果都一样

      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.exceptions.PersistenceException;
     15 import org.apache.ibatis.executor.BatchResult;
     16 import org.apache.ibatis.reflection.ExceptionUtil;
     17 import org.apache.ibatis.session.Configuration;
     18 import org.apache.ibatis.session.ExecutorType;
     19 import org.apache.ibatis.session.ResultHandler;
     20 import org.apache.ibatis.session.RowBounds;
     21 import org.apache.ibatis.session.SqlSession;
     22 import org.apache.ibatis.session.SqlSessionFactory;
     23 import org.springframework.dao.support.PersistenceExceptionTranslator;
     24 import org.springframework.util.Assert;
     25 
     26 public class SqlSessionTemplate implements SqlSession {
     27     private final SqlSessionFactory sqlSessionFactory;
     28     private final ExecutorType executorType;
     29     private final SqlSession sqlSessionProxy;
     30     private final PersistenceExceptionTranslator exceptionTranslator;
     31 
     32     public SqlSessionTemplate(SqlSessionFactory sqlSessionFactory) {
     33         this(sqlSessionFactory, sqlSessionFactory.getConfiguration().getDefaultExecutorType());
     34     }
     35 
     36     public SqlSessionTemplate(SqlSessionFactory sqlSessionFactory, ExecutorType executorType) {
     37         this(sqlSessionFactory, executorType, new MyBatisExceptionTranslator(sqlSessionFactory.getConfiguration().getEnvironment().getDataSource(), true));
     38     }
     39 
     40     public SqlSessionTemplate(SqlSessionFactory sqlSessionFactory, ExecutorType executorType, PersistenceExceptionTranslator exceptionTranslator) {
     41         Assert.notNull(sqlSessionFactory, "Property 'sqlSessionFactory' is required");
     42         Assert.notNull(executorType, "Property 'executorType' is required");
     43         this.sqlSessionFactory = sqlSessionFactory;
     44         this.executorType = executorType;
     45         this.exceptionTranslator = exceptionTranslator;
     46         this.sqlSessionProxy = (SqlSession)Proxy.newProxyInstance(SqlSessionFactory.class.getClassLoader(), new Class[]{SqlSession.class}, new SqlSessionTemplate.SqlSessionInterceptor());
     47     }
     48 
     49     public SqlSessionFactory getSqlSessionFactory() {
     50         return this.sqlSessionFactory;
     51     }
     52 
     53     public ExecutorType getExecutorType() {
     54         return this.executorType;
     55     }
     56 
     57     public PersistenceExceptionTranslator getPersistenceExceptionTranslator() {
     58         return this.exceptionTranslator;
     59     }
     60 
     61     public <T> T selectOne(String statement) {
     62         return this.sqlSessionProxy.selectOne(statement);
     63     }
     64 
     65     public <T> T selectOne(String statement, Object parameter) {
     66         return this.sqlSessionProxy.selectOne(statement, parameter);
     67     }
     68 
     69     public <K, V> Map<K, V> selectMap(String statement, String mapKey) {
     70         return this.sqlSessionProxy.selectMap(statement, mapKey);
     71     }
     72 
     73     public <K, V> Map<K, V> selectMap(String statement, Object parameter, String mapKey) {
     74         return this.sqlSessionProxy.selectMap(statement, parameter, mapKey);
     75     }
     76 
     77     public <K, V> Map<K, V> selectMap(String statement, Object parameter, String mapKey, RowBounds rowBounds) {
     78         return this.sqlSessionProxy.selectMap(statement, parameter, mapKey, rowBounds);
     79     }
     80 
     81     public <E> List<E> selectList(String statement) {
     82         return this.sqlSessionProxy.selectList(statement);
     83     }
     84 
     85     public <E> List<E> selectList(String statement, Object parameter) {
     86         return this.sqlSessionProxy.selectList(statement, parameter);
     87     }
     88 
     89     public <E> List<E> selectList(String statement, Object parameter, RowBounds rowBounds) {
     90         return this.sqlSessionProxy.selectList(statement, parameter, rowBounds);
     91     }
     92 
     93     public void select(String statement, ResultHandler handler) {
     94         this.sqlSessionProxy.select(statement, handler);
     95     }
     96 
     97     public void select(String statement, Object parameter, ResultHandler handler) {
     98         this.sqlSessionProxy.select(statement, parameter, handler);
     99     }
    100 
    101     public void select(String statement, Object parameter, RowBounds rowBounds, ResultHandler handler) {
    102         this.sqlSessionProxy.select(statement, parameter, rowBounds, handler);
    103     }
    104 
    105     public int insert(String statement) {
    106         return this.sqlSessionProxy.insert(statement);
    107     }
    108 
    109     public int insert(String statement, Object parameter) {
    110         return this.sqlSessionProxy.insert(statement, parameter);
    111     }
    112 
    113     public int update(String statement) {
    114         return this.sqlSessionProxy.update(statement);
    115     }
    116 
    117     public int update(String statement, Object parameter) {
    118         return this.sqlSessionProxy.update(statement, parameter);
    119     }
    120 
    121     public int delete(String statement) {
    122         return this.sqlSessionProxy.delete(statement);
    123     }
    124 
    125     public int delete(String statement, Object parameter) {
    126         return this.sqlSessionProxy.delete(statement, parameter);
    127     }
    128 
    129     public <T> T getMapper(Class<T> type) {
    130         return this.getConfiguration().getMapper(type, this);
    131     }
    132 
    133     public void commit() {
    134         throw new UnsupportedOperationException("Manual commit is not allowed over a Spring managed SqlSession");
    135     }
    136 
    137     public void commit(boolean force) {
    138         throw new UnsupportedOperationException("Manual commit is not allowed over a Spring managed SqlSession");
    139     }
    140 
    141     public void rollback() {
    142         throw new UnsupportedOperationException("Manual rollback is not allowed over a Spring managed SqlSession");
    143     }
    144 
    145     public void rollback(boolean force) {
    146         throw new UnsupportedOperationException("Manual rollback is not allowed over a Spring managed SqlSession");
    147     }
    148 
    149     public void close() {
    150         throw new UnsupportedOperationException("Manual close is not allowed over a Spring managed SqlSession");
    151     }
    152 
    153     public void clearCache() {
    154         this.sqlSessionProxy.clearCache();
    155     }
    156 
    157     public Configuration getConfiguration() {
    158         return this.sqlSessionFactory.getConfiguration();
    159     }
    160 
    161     public Connection getConnection() {
    162         return this.sqlSessionProxy.getConnection();
    163     }
    164 
    165     public List<BatchResult> flushStatements() {
    166         return this.sqlSessionProxy.flushStatements();
    167     }
    168 
    169     private class SqlSessionInterceptor implements InvocationHandler {
    170         private SqlSessionInterceptor() {
    171         }
    172 
    173         public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
    174             SqlSession sqlSession = SqlSessionUtils.getSqlSession(SqlSessionTemplate.this.sqlSessionFactory, SqlSessionTemplate.this.executorType, SqlSessionTemplate.this.exceptionTranslator);
    175 
    176             Object unwrapped;
    177             try {
    178                 Object result = method.invoke(sqlSession, args);
    179                 if (!SqlSessionUtils.isSqlSessionTransactional(sqlSession, SqlSessionTemplate.this.sqlSessionFactory)) {
    180                     sqlSession.commit(true);
    181                 }
    182 
    183                 unwrapped = result;
    184             } catch (Throwable var11) {
    185                 unwrapped = ExceptionUtil.unwrapThrowable(var11);
    186                 if (SqlSessionTemplate.this.exceptionTranslator != null && unwrapped instanceof PersistenceException) {
    187                     SqlSessionUtils.closeSqlSession(sqlSession, SqlSessionTemplate.this.sqlSessionFactory);
    188                     sqlSession = null;
    189                     Throwable translated = SqlSessionTemplate.this.exceptionTranslator.translateExceptionIfPossible((PersistenceException)unwrapped);
    190                     if (translated != null) {
    191                         unwrapped = translated;
    192                     }
    193                 }
    194 
    195                 throw (Throwable)unwrapped;
    196             } finally {
    197                 if (sqlSession != null) {
    198                     SqlSessionUtils.closeSqlSession(sqlSession, SqlSessionTemplate.this.sqlSessionFactory);
    199                 }
    200 
    201             }
    202 
    203             return unwrapped;
    204         }
    205     }
    206 }
  • 相关阅读:
    android 中文 api (43) —— Chronometer
    SVN客户端清除密码
    Android 中文 API (35) —— ImageSwitcher
    Android 中文API (46) —— SimpleAdapter
    Android 中文 API (28) —— CheckedTextView
    Android 中文 API (36) —— Toast
    Android 中文 API (29) —— CompoundButton
    android 中文 API (41) —— RatingBar.OnRatingBarChangeListener
    Android 中文 API (30) —— CompoundButton.OnCheckedChangeListener
    Android 中文 API (24) —— MultiAutoCompleteTextView.CommaTokenizer
  • 原文地址:https://www.cnblogs.com/xiexin2015/p/8998331.html
Copyright © 2020-2023  润新知