游戏电视苹果数码历史美丽
投稿投诉
美丽时装
彩妆资讯
历史明星
乐活安卓
数码常识
驾车健康
苹果问答
网络发型
电视车载
室内电影
游戏科学
音乐整形

Mybatis数据源模块

  Mybatis数据源模块
  本篇学习Mybatis的数据源模块
  org。apache。ibatis。datasource数据源模块要做什么
  数据源模块要实现的功能:常见的数据源组件都实现了javax。sql。DataSource接口;MyBatis不但要能集成第三方的数据源组件,自身也提供了数据源的实现;一般情况下,数据源的初始化过程参数较多,比较复杂
  首先我们创建dataSource的过程是非常复杂的。而且我们有需要方便扩展。因此我们可以使用工厂模式(创建型的模式)
  工厂模式可以查看我之前写的一篇https:mp。toutiao。comprofilev4graphicpreview?pgcid7008076815566717447整个包结构
  从这个包结构也可以看出来数据源模块整体的设计是一个工厂模式。unpooled:非连接池pooled:连接处jndi:容器连接如tomcat等。(这个我们本次不进行解析)源码解析
  先来看下抽象工厂类:publicinterfaceDataSourceFactory{设置dataSource属性voidsetProperties(Propertiesprops);获取dataSourceDataSourcegetDataSource();}非连接池包
  非连接池包里面一共就2个类UnpooledDataSourceFactoryUnpooledDataSource
  UnpooledDataSourceFactory是实现了抽象工厂DataSourceFactory的类。
  UnpooledDataSource则是上面工厂类实际的调用的类
  我们先看下UnpooledDataSourcepublicclassUnpooledDataSourceimplementsDataSource{数据库驱动privateClassLoaderdriverClassLoader;数据库连接相关配置信息privatePropertiesdriverProperties;驱动的注册中心privatestaticMapString,DriverregisteredDriversnewConcurrentHashMap();数据库连接的一些属性privateStringdriver;privateStringurl;privateStringusername;privateStringpassword;是否自动提交事务privateBooleanautoCommit;默认事务级别privateIntegerdefaultTransactionIsolationLevel;默认超时时间privateIntegerdefaultNetworkTimeout;使用静态代码快将驱动注册到DriverManage这个地方和MysqlDriver里面的原理大致一致static{EnumerationDriverdriversDriverManager。getDrivers();while(drivers。hasMoreElements()){Driverdriverdrivers。nextElement();registeredDrivers。put(driver。getClass()。getName(),driver);}}一大波构造函数和setter。。。获取conn通过用户名和密码privateConnectiondoGetConnection(Stringusername,Stringpassword)throwsSQLException{PropertiespropsnewProperties();if(driverProperties!null){props。putAll(driverProperties);}if(username!null){props。setProperty(user,username);}if(password!null){props。setProperty(password,password);}returndoGetConnection(props);}获取conn通过配置文件privateConnectiondoGetConnection(Propertiesproperties)throwsSQLException{initializeDriver();ConnectionconnectionDriverManager。getConnection(url,properties);设置事务是否自动提交,事务的隔离级别configureConnection(connection);returnconnection;}privatesynchronizedvoidinitializeDriver()throwsSQLException{if(!registeredDrivers。containsKey(driver)){Classlt;?driverType;try{if(driverClassLoader!null){driverTypeClass。forName(driver,true,driverClassLoader);}else{driverTypeResources。classForName(driver);}DriverManagerrequiresthedrivertobeloadedviathesystemClassLoader。http:www。kfu。comnsayerJavadynjdbc。htmlDriverdriverInstance(Driver)driverType。getDeclaredConstructor()。newInstance();DriverManager。registerDriver(newDriverProxy(driverInstance));registeredDrivers。put(driver,driverInstance);}catch(Exceptione){thrownewSQLException(ErrorsettingdriveronUnpooledDataSource。Cause:e);}}}配置超时时间、自动提交、事务privatevoidconfigureConnection(Connectionconn)throwsSQLException{if(defaultNetworkTimeout!null){conn。setNetworkTimeout(Executors。newSingleThreadExecutor(),defaultNetworkTimeout);}if(autoCommit!nullautoCommit!conn。getAutoCommit()){conn。setAutoCommit(autoCommit);}if(defaultTransactionIsolationLevel!null){conn。setTransactionIsolation(defaultTransactionIsolationLevel);}}。。。}
  我们在继续看下工厂类UnpooledDataSourceFactoryauthorClintonBegin子类工厂对应的产品为UnpooledDataSourcepublicclassUnpooledDataSourceFactoryimplementsDataSourceFactory{privatestaticfinalStringDRIVERPROPERTYPREFIXdriver。;privatestaticfinalintDRIVERPROPERTYPREFIXLENGTHDRIVERPROPERTYPREFIX。length();protectedDataSourcedataSource;publicUnpooledDataSourceFactory(){this。dataSourcenewUnpooledDataSource();}OverridepublicvoidsetProperties(Propertiesproperties){PropertiesdriverPropertiesnewProperties();创建DataSource相应的metaObject,方便赋值MetaObjectmetaDataSourceSystemMetaObject。forObject(dataSource);遍历properties,将属性设置到DataSource中for(Objectkey:properties。keySet()){StringpropertyName(String)key;if(propertyName。startsWith(DRIVERPROPERTYPREFIX)){Stringvalueproperties。getProperty(propertyName);driverProperties。setProperty(propertyName。substring(DRIVERPROPERTYPREFIXLENGTH),value);}elseif(metaDataSource。hasSetter(propertyName)){Stringvalue(String)properties。get(propertyName);ObjectconvertedValueconvertValue(metaDataSource,propertyName,value);metaDataSource。setValue(propertyName,convertedValue);}else{thrownewDataSourceException(UnknownDataSourceproperty:propertyName);}}设置DataSource。driverProperties属性if(driverProperties。size()0){metaDataSource。setValue(driverProperties,driverProperties);}}OverridepublicDataSourcegetDataSource(){returndataSource;}。。。}连接池包
  连接池包中类多了几个PooledDataSourceFactory:工厂类PoolState:用于管理PooledConnection对象状态的组件PooledConnection:数据库连接对象PooledDataSource:数据库连接池
  直接贴源码分析:
  PooledDataSourceFactory继承了UnpooledDataSourceFactoryUnpooledDataSourceFactory实现了最基本的抽象工厂接口publicclassPooledDataSourceFactoryextendsUnpooledDataSourceFactory{publicPooledDataSourceFactory(){this。dataSourcenewPooledDataSource();}}
  PoolStateauthorClintonBeginPoolState:用于管理PooledConnection对象状态的组件,通过两个list分别,管理空闲状态的连接资源和活跃状态的连接资源并且提供了一些属性来记录时间次数等publicclassPoolState{protectedPooledDataSourcedataSource;空闲的连接池资源集合protectedfinalListPooledConnectionidleConnectionsnewArrayList();活跃的连接池资源集合protectedfinalListPooledConnectionactiveConnectionsnewArrayList();请求的次数protectedlongrequestCount0;累计的获得连接的时间protectedlongaccumulatedRequestTime0;累计的使用连接的时间。从连接取出到归还,算一次使用的时间;protectedlongaccumulatedCheckoutTime0;连接超时的次数protectedlongclaimedOverdueConnectionCount0;累计超时时间protectedlongaccumulatedCheckoutTimeOfOverdueConnections0;累计等待时间protectedlongaccumulatedWaitTime0;等待次数protectedlonghadToWaitCount0;连接失败次数protectedlongbadConnectionCount0;。。。}
  PooledConnectionauthorClintonBegin数据库连接对象采用了动态代理的方式classPooledConnectionimplementsInvocationHandler{privatestaticfinalStringCLOSEclose;privatestaticfinalClasslt;?〔〕IFACESnewClasslt;?〔〕{Connection。class};privatefinalinthashCode;记录当前连接所在的数据源对象,本次连接是由这个数据源创建的,关闭后也是回到这个数据源;可以理解为这个对象是提供给客户端使用的privatefinalPooledDataSourcedataSource;真实的连接对象privatefinalConnectionrealConnection;代理连接对象privatefinalConnectionproxyConnection;连接时间戳连接上数据源的时间privatelongcheckoutTimestamp;创建时间戳创建连接的时间privatelongcreatedTimestamp;最后一次使用时间戳privatelonglastUsedTimestamp;这个属性标志唯一连接池,由数据库url、用户名、密码生成一个hash值privateintconnectionTypeCode;连接是否还有效privatebooleanvalid;ConstructorforSimplePooledConnectionthatusestheConnectionandPooledDataSourcepassedin。paramconnectiontheconnectionthatistobepresentedasapooledconnectionparamdataSourcethedataSourcethattheconnectionisfrompublicPooledConnection(Connectionconnection,PooledDataSourcedataSource){this。hashCodeconnection。hashCode();this。realConnectionconnection;this。dataSourcedataSource;this。createdTimestampSystem。currentTimeMillis();this。lastUsedTimestampSystem。currentTimeMillis();this。validtrue;这里使用了动态代理来设置代理对象,这个代理对象最后在获取连接的时候会返回给调用Mybatis的一方this。proxyConnection(Connection)Proxy。newProxyInstance(Connection。class。getClassLoader(),IFACES,this);}。。。}
  PooledDataSource这个类是核心类了,获取和归还连接都是由这个类来完成的,我这边也仅对几个核心的方法进行分析publicclassPooledDataSourceimplementsDataSource{privatestaticfinalLoglogLogFactory。getLog(PooledDataSource。class);privatefinalPoolStatestatenewPoolState(this);数据源privatefinalUnpooledDataSourcedataSource;OPTIONALCONFIGURATIONFIELDS最大连接数protectedintpoolMaximumActiveConnections10;最大闲置连接数protectedintpoolMaximumIdleConnections5;最大的校验时间protectedintpoolMaximumCheckoutTime20000;最长等待时间protectedintpoolTimeToWait20000;最多几次允许几次无效连接protectedintpoolMaximumLocalBadConnectionTolerance3;测试连接是否有效的sql语句protectedStringpoolPingQueryNOPINGQUERYSET;是否允许测试连接protectedbooleanpoolPingEnabled;连接在这个配置时间内没有被使用,才允许测试连接是否有效protectedintpoolPingConnectionsNotUsedFor;连接池的唯一标志:根据数据库url、用户名、密码生成一个hash值privateintexpectedConnectionTypeCode;归还连接paramconnthrowsSQLExceptionprotectedvoidpushConnection(PooledConnectionconn)throwsSQLException{同样归还连接的时候也要加锁synchronized(state){先从活跃线程队列中移除state。activeConnections。remove(conn);if(conn。isValid()){判断闲置连接池资源是否已经达到上限if(state。idleConnections。size()poolMaximumIdleConnectionsconn。getConnectionTypeCode()expectedConnectionTypeCode){state。accumulatedCheckoutTimeconn。getCheckoutTime();if(!conn。getRealConnection()。getAutoCommit()){conn。getRealConnection()。rollback();}没有达到上线就创建新的连接(这个新连接实际上就是上面的归还的连接)放入空闲线程中PooledConnectionnewConnnewPooledConnection(conn。getRealConnection(),this);state。idleConnections。add(newConn);newConn。setCreatedTimestamp(conn。getCreatedTimestamp());newConn。setLastUsedTimestamp(conn。getLastUsedTimestamp());将连接对象设置为无效conn。invalidate();if(log。isDebugEnabled()){log。debug(ReturnedconnectionnewConn。getRealHashCode()topool。);}唤醒其他等待线程这个很重要,在我们获取连接的时候如果实在是没有连接就会让线程处于阻塞状态state。notifyAll();}else{state。accumulatedCheckoutTimeconn。getCheckoutTime();if(!conn。getRealConnection()。getAutoCommit()){conn。getRealConnection()。rollback();}如果闲置连接池已经达到上限了,将连接真实关闭conn。getRealConnection()。close();if(log。isDebugEnabled()){log。debug(Closedconnectionconn。getRealHashCode()。);}将连接对象设置为无效conn。invalidate();}}else{if(log。isDebugEnabled()){log。debug(Abadconnection(conn。getRealHashCode())attemptedtoreturntothepool,discardingconnection。);}state。badConnectionCount;}}}获取数据库连接paramusernameparampasswordreturnthrowsSQLException整个流程分为两部分1。获取连接2。对获取的连接做池化数据的信息处理第一部分:循环判断获取连接是否为空优先从空闲连接中获取连接有:空闲连接就进入第二部分没有:判断是否可以新增连接(活跃连接数是否已达到最大连接数)若没到最大线程数则直接创建俩姐进入第二部分若无法新增连接,则检查是否存在超时的连接,如果有就使用这个连接,没有则进入阻塞状态第二部分:修改线程的活跃线程数,请求次数等。(PoolState)privatePooledConnectionpopConnection(Stringusername,Stringpassword)throwsSQLException{booleancountedWaitfalse;PooledConnectionconnnull;longtSystem。currentTimeMillis();intlocalBadConnectionCount0;这里是一个循环,直到拿到conn,不然就会一致循环下去循环体中有超时和超次机制while(connnull){使用synchronized来处理多线程间的同步synchronized(state){检查是否还有空闲线程,不为空表示有if(!state。idleConnections。isEmpty()){Poolhasavailableconnection有空闲线程则将线程从线程池的空闲队列中拿出第一个线程(这里会减少空闲线程数量)connstate。idleConnections。remove(0);if(log。isDebugEnabled()){log。debug(Checkedoutconnectionconn。getRealHashCode()frompool。);}}else{当没有空闲线程时,判断活跃线程数是否已经达到最大线程数Pooldoesnothaveavailableconnectionif(state。activeConnections。size()poolMaximumActiveConnections){Cancreatenewconnection创建新的连接connnewPooledConnection(dataSource。getConnection(),this);if(log。isDebugEnabled()){log。debug(Createdconnectionconn。getRealHashCode()。);}}else{Cannotcreatenewconnection无法创建心对连接,则检查线程池中最早的线程是否超时。若超时则将连接释放出来PooledConnectionoldestActiveConnectionstate。activeConnections。get(0);longlongestCheckoutTimeoldestActiveConnection。getCheckoutTime();if(longestCheckoutTimepoolMaximumCheckoutTime){Canclaimoverdueconnectionstate。claimedOverdueConnectionCount;state。accumulatedCheckoutTimeOfOverdueConnectionslongestCheckoutTime;state。accumulatedCheckoutTimelongestCheckoutTime;state。activeConnections。remove(oldestActiveConnection);if(!oldestActiveConnection。getRealConnection()。getAutoCommit()){try{oldestActiveConnection。getRealConnection()。rollback();}catch(SQLExceptione){Justlogamessagefordebugandcontinuetoexecutethefollowingstatementlikenothinghappened。WrapthebadconnectionwithanewPooledConnection,thiswillhelptonotinterruptcurrentexecutingthreadandgivecurrentthreadachancetojointhenextcompetitionforanothervalidgooddatabaseconnection。Attheendofthisloop,bad{linkconn}willbesetasnull。log。debug(Badconnection。Couldnotrollback);}}在连接池中创建新的连接,注意对于数据库来说,并没有创建新连接;connnewPooledConnection(oldestActiveConnection。getRealConnection(),this);conn。setCreatedTimestamp(oldestActiveConnection。getCreatedTimestamp());conn。setLastUsedTimestamp(oldestActiveConnection。getLastUsedTimestamp());oldestActiveConnection。invalidate();if(log。isDebugEnabled()){log。debug(Claimedoverdueconnectionconn。getRealHashCode()。);}}else{Mustwait实在是没有连接可以用了,就阻塞等到try{if(!countedWait){state。hadToWaitCount;countedWaittrue;}if(log。isDebugEnabled()){log。debug(WaitingaslongaspoolTimeToWaitmillisecondsforconnection。);}longwtSystem。currentTimeMillis();state。wait(poolTimeToWait);state。accumulatedWaitTimeSystem。currentTimeMillis()wt;}catch(InterruptedExceptione){break;}}}}上面的循环已经拿到了conn这里做一个二次校验if(conn!null){pingtoserverandchecktheconnectionisvalidornot检测连接是否有效if(conn。isValid()){这里获取的是真实连接的自动提交属性,如果不是自动提交,就将事务回滚这么做是因为获取的连接有可能是超时连接,但是本身连接中还有事务在运行if(!conn。getRealConnection()。getAutoCommit()){conn。getRealConnection()。rollback();}设置连接池相关统计信息更新conn。setConnectionTypeCode(assembleConnectionTypeCode(dataSource。getUrl(),username,password));conn。setCheckoutTimestamp(System。currentTimeMillis());conn。setLastUsedTimestamp(System。currentTimeMillis());state。activeConnections。add(conn);state。requestCount;state。accumulatedRequestTimeSystem。currentTimeMillis()t;}else{如果连接无效if(log。isDebugEnabled()){log。debug(Abadconnection(conn。getRealHashCode())wasreturnedfromthepool,gettinganotherconnection。);}累计的获取无效连接次数1state。badConnectionCount;当前获取无效连接次数1localBadConnectionCount;connnull;拿到无效连接,但如果没有超过重试的次数,则重新走上面的while循环允许再次尝试获取连接,否则抛出异常if(localBadConnectionCount(poolMaximumIdleConnectionspoolMaximumLocalBadConnectionTolerance)){if(log。isDebugEnabled()){log。debug(PooledDataSource:Couldnotgetagoodconnectiontothedatabase。);}thrownewSQLException(PooledDataSource:Couldnotgetagoodconnectiontothedatabase。);}}}}}if(connnull){if(log。isDebugEnabled()){log。debug(PooledDataSource:Unknownsevereerrorcondition。Theconnectionpoolreturnedanullconnection。);}thrownewSQLException(PooledDataSource:Unknownsevereerrorcondition。Theconnectionpoolreturnedanullconnection。);}returnconn;}}
  整体流程图:
  壁纸图,侵权删

拜见宫主大人2脑洞升级关智斌网恋产子星关系4月24日讯近日,反套路热血武侠喜剧《拜见宫主大人2》正在搜狐视频热播。该剧由关智斌、孙雪宁领衔主演,一经开播口碑与网播量齐飞,一度攀登热搜榜。剧中,关智斌饰演魔王秦斩,……截至现在,拍照最佳的三款手机,均是影像机皇标准手机拍照性能好不好已经成为了大家买手机的重要参考之一,喜欢自拍或者喜欢旅行拍照的朋友可能会把这一点作为首要考虑的标准,没有唯一。而手机厂商开发布会的时候,也会把手机的拍照单独拎……恒大的违约风险正在攀升。有没有人分析一下,恒大以后会怎样?恒大倒闭的第一张骨牌是从强行债转股开始(如苏宁就是这次债转股损失二百亿被害死),那些借钱给恒大的债权人一不小心变成了股东,然后恒大在资本市场很难融到资了。第二张骨牌是20年政策……手机贬值三个不同型号旧手机回收多少钱?最低报价1元测试使用APP为:转转手机1华为NOVA7:(购入时间2019年,国行、全网通、6G128G、账号可退出,外观无划痕能正常使用)预估价格:684元这个价……王智骞首拍网剧深宫丑女萌犬系男友暖心上线星关系1月28日讯24集甜宠暖萌超级网剧《深宫丑女》近日在横店热拍,该网剧根据同名畅销小说及人气漫画改编,由罗至中执导,阳光光编剧,新晋演员王智骞携手何花、罗一航、文苡帆等演员……恒大汽车会功亏一篑,还是成功翻盘债务危机下的造车迷局新能源汽车之风刮起后,有的车企飞黄腾达,成了天上的星辰,有的车企则一败涂地,成了地上的灰尘。自2015年至今,造车大军之路,横尸遍野,倒下的大大小小的车企不胜枚举,有的是……法医秦明之读心者开机00后演员陈天一挑战悬疑题材由秦明所著的系列悬疑小说《尸语者》改编的电视剧《法医秦明之读心者》于4月12日在青岛开机,中国香港导演施磊执导,由张耀、汤敏、彭楚粤、马昕墨等主演,成为年纪最小的秦明探案团。……无版号主机游戏禁售,线上线下均遭严打京东开列游戏黑名单9月2日,京东发布一则关于禁售游戏的公告称,将禁售游戏包含但不限于一下表格所列的87款游戏。公告中京东表示,为了规范网络游戏经营秩序、维护健康和谐的网络文化环境,根据《中……法医秦明完美收官余心恬华丽蜕变演技升级星关系9月14日讯由企鹅影视、聚禾影画影业和公安部金盾影视文化中心联合出品,秦明担任总编剧,周琳皓执导,经超、刘海宽、余心恬、邓炀、艾晓琪等联袂主演的《法医秦明之幸存者》(以下……碳捕捉关键技术或突破!比尔盖茨注资这家公司智通财经APP获悉,总部位于马萨诸塞州的一家碳捕捉初创公司VerdoxInc。已从投资者那里筹集了8000万美元,其中包括比尔盖茨旗下BreakthroughEnergyVen……金莎霸气自称大龙女网友杀青了就快点出戏啊星关系1月10日讯1月9日,金莎晒出一组剧照,并表示要是早生二十年,我就是大龙女,就没小龙女什么事儿了。照片中,金莎身着素色长袍,披肩与长袍的别致连接,和头上的龙角配饰相互映衬……仙剑奇侠传五前传曝光概念海报主演花落谁家引发期待由爱奇艺、时代光影联合出品,时代光影负责承制,改编自经典同名IP的古装仙侠剧《仙剑奇侠传五前传》于今日公布概念海报并发布组讯,关于剧中的经典角色由谁出演,引发了网友热议。……
怎样用2个手机号注册N个微信号2个手机号怎么申请多个微信号?现代社会不断信息化,科技也越来越发达,许多工作上的事情都是在微信上交流,所以有很多人都想有多个微信号能更方便点。工作时用工作号,生活上……堪比小型发电机,在户外还能煮饭,爱国者户外储能电源评测夏季关联最多的两个字是什么?当然是踏青,无论是一家人还是和同事团建户外活动永远是最佳的选择,对于东北人来说烧烤一直是最爱的美食,在户外使用明火烧烤一来是有安全隐患,特别是户外的……三星GalaxyZFold35G引入新技术,屏下摄像头技术,近些年,虽然新技术应用层出不穷,但智能机的发展趋势依然做到了一个瓶颈,造成销售市场单一化状况更加比较严重,而折叠屏手机上的发生,变成了手机上在历史上重特大的形状转型,使我们看到……开了一年比亚迪唐DM,再看威兰达高性能版,感叹以前盲目自信了我5年前就有买车的打算,只不过当时房贷压力有些大,再加上一直摇不到号,所以就一拖再拖。直到一年前实在受不了了,就打算买一款绿牌车,通过这几年的发展,感觉新能源技术可靠性已经不错……任正非再次ampampquot点名批评ampampquot!【8月12日讯】相信大家都知道,华为作为国内实力最强的民营科技巨头,具备了全球领先的科研能力,如今在芯片、5G通讯技术、手机终端甚至是操作系统领域,都有着超强的研发水准,而就在……罕见科技!让手机跟笔记本合二为一?这个电脑品牌做到了。在如今科技发展迅速的时代,大部分手机以及电脑厂商都在扩展自家外观以及性能上大动脑筋,比如说如今的三星华为等,都在手机外观和性能上增添了不少的独家黑科技,为之不同的是在去年,一直……新款比亚迪唐EV工况续航达到700公里了近日,中华网汽车从工信部获悉,在今年第7批新能源汽车推广应用推荐车型目录中,我们发现了比亚迪新车的多款信息,其中比亚迪的旗舰SUV唐EV的工况续航将再次提升,其工况续航将达到7……英国开发人形机器人逼真表情背后藏着哪些秘密?来源:成都商报Ameca莞尔一笑全世界大吃一惊英国开发的这款人形机器人逼真表情背后藏着哪些秘密?近日,由英国科技公司EngineeredArts开发的人形机器人Am……断臂搜狗后,畅游成为搜狐优质资产,张朝阳这盘棋下的有点大作为中国最老牌的互联网公司之一,搜狐在PC互联网时代可以说是独领风骚。但是互联网行业每时每刻都在发生着新的变化,转眼间,移动互联网时代降临了。曾经的四大门户新浪、网……美方称英特尔公司不应为维护人权而道歉,外交部倒打一耙来源:澎湃新闻12月24日,外交部发言人赵立坚主持例行记者会。有记者提问,23日,美国白宫发言人就英特尔发表新疆供应链声明称,私营部门和国际社会应该反对中国将其市场武器化……iPhone12mini不受欢迎!为何库克还推出13mini此前,果粉们对于iPhonemini版产品的呼声一直很高。但这种呼声到iPhone12mini版本推出之后戛然而止。从iPhone12mini是整个iPhone12系列当……英伟达秀了一把AI方面的硬实力,还为旧显卡下放了光线追踪技术恰逢游戏开发者大会GDC2019和GPU技术峰会GTC2019两场大会的开幕,近日,英伟达正式宣布了一系列涵盖了AI、自动驾驶、云游戏、计算和GeForce等方面的技术、产品以……
友情链接:易事利快生活快传网聚热点七猫云快好知快百科中准网快好找文好找中准网快软网