文:宋瑞文
本站聲明:網站內容來源環境資訊中心https://e-info.org.tw/,如有侵權,請聯繫我們,我們將及時處理
【其他文章推薦】
※為什麼 USB CONNECTOR 是電子產業重要的元件?
※網頁設計一頭霧水該從何著手呢? 台北網頁設計公司幫您輕鬆架站!
※台北網頁設計公司全省服務真心推薦
※想知道最厲害的網頁設計公司"嚨底家"!
※推薦評價好的iphone維修中心
上一篇說了mysql的架構圖,很多同學反饋說不過癮,畢竟還是聽我講故事,那這篇就來說一說怎麼利用visual studio 對 mysql進行源碼級調試,畢竟源碼面前,不談隱私,聖人面前,皆為螻蟻。
mysql是C++寫的,要想在windows上編譯,還需要下載幾個必備小工具。
這裏簡單說一下:可以用 cmake 將源碼生成 *.sln 可打開的解決方案,比如可以通過它最終生成 MySQL.sln。boost 是C++中非常強大的基礎庫,bison 一個流行的語法分析器程序,用於給mysql提供語法分析,最後就是下載正確的mysql版本5.7.12。
我會寫的比較細,畢竟我也花了一下午時間,寒酸(┬_┬)
cmake 和 bison 安裝起來比較方便,一鍵安裝就可以了,不過這裡有一個大坑注意了,在安裝Bison的時候,千萬不要使用默認路徑,因為默認路徑有空格,會導致你後面vs編譯的時候卡住,又不显示什麼原因,可氣!!! 所以我換成自定義的: C:\2\GnuWin32。
最後確保 cmake 和 bison 的bin文件都在 環境變量中即可。
這裏我用 C:\2
作為根文件夾,所有的小工具都在這裏,如圖:
接下來將 mysql-5.7.12.zip
解壓一下,然後進入解壓后的文件夾,新建一個boost文件夾,將boost_1_59_0.tar.gz放入其中,然後再新建一個 brelease 文件夾可用於存放最終生成的MySql.sln
。。
都準備好了之後,可以開始cmake編譯了。
PS C:\2\mysql-5.7.12\brelease> cmake .. -DDOWNLOAD_BOOST=1 -DWITH_BOOST="C:\2\mysql-5.7.12\boost\boost_1_59_0.tar.gz"
-- Building for: Visual Studio 16 2019
CMake Deprecation Warning at CMakeLists.txt:26 (CMAKE_POLICY):
The OLD behavior for policy CMP0018 will be removed from a future version
of CMake.
-- Cannot find wix 3, installer project will not be generated
-- COMPILE_DEFINITIONS: _WIN32_WINNT=0x0601;WIN32_LEAN_AND_MEAN;NOGDI;NOMINMAX;HAVE_CONFIG_H
-- CMAKE_C_FLAGS: /DWIN32 /D_WINDOWS /W3 /MP /wd4800 /wd4805 /wd4996
-- CMAKE_CXX_FLAGS: /DWIN32 /D_WINDOWS /W3 /GR /EHsc /MP /wd4800 /wd4805 /wd4996 /we4099
-- CMAKE_C_FLAGS_DEBUG: /MTd /Z7 /Ob1 /Od /RTC1 /EHsc -DENABLED_DEBUG_SYNC -DSAFE_MUTEX
-- CMAKE_CXX_FLAGS_DEBUG: /MTd /Z7 /Ob1 /Od /RTC1 /EHsc -DENABLED_DEBUG_SYNC -DSAFE_MUTEX
-- CMAKE_C_FLAGS_RELWITHDEBINFO: /MT /Z7 /O2 /Ob1 /DNDEBUG /EHsc -DDBUG_OFF
-- CMAKE_CXX_FLAGS_RELWITHDEBINFO: /MT /Z7 /O2 /Ob1 /DNDEBUG /EHsc -DDBUG_OFF
-- Configuring done
-- Generating done
-- Build files have been written to: C:/2/mysql-5.7.12/brelease
當看到最後一句 Build files have been written to: C:/2/mysql-5.7.12/brelease
,恭喜你,MySQL.sln
生成好了。
我的電腦安裝的是visual studio 2019
,接下來打開MySql.Sln整體編譯,需要等個十幾分鐘,看到下面的輸出就算安裝成功。
這裏要做兩件事情,第一件事是將mysql的調試模式打開,第二件事就是附加 --initialize
啟動參數。
修改C:\2\mysql-5.7.12\sql\mysqld.cc
中的 test_lc_time_sz
方法中的 DBUG_ASSERT(0); 改成 DBUG_ASSERT(1); 如下圖:
上一篇大家都知道了,mysqld項目是mysql的啟動項目,main函數也在其中,在F5調試之前增加初始化參數 --console --initialize
,如下圖:
啟動之後,有103個報錯,氣人呀。。。看錯誤信息應該是編碼問題,如下圖:
修改起來也很簡單,將 C:\2\mysql-5.7.12\sqlsql_locale.cc
用 [utf-8 + BOM] 格式保存一下,然後對mysqld項目Rebuild再Ctrl+F5
直接運行,終於謝天謝地,從輸出可以看到,搞定啦。。。太不容易啦。
從上圖中可以看到,默認密碼是:zJDE>IC5o+ya,先記錄下這個密碼,然後再把CommandLine Arguments 中的–initialize去掉再重啟Console。
可以看到,3306端口已開啟,然後用剛才的 zJDE>IC5o+ya 連接即可,這裏我使用navicat。
連接上去後會提示修改默認密碼,設置我就設置為:123456 ,嘿嘿,一切搞定~~~
上一篇我們追蹤到了 write_row 就斷掉了,我當時說它是一個虛方法,由底層具體的存儲引擎去調用,代碼如下:
int handler::ha_write_row(uchar *buf)
{
MYSQL_TABLE_IO_WAIT(m_psi, PSI_TABLE_WRITE_ROW, MAX_KEY, 0,{ error= write_row(buf); })
}
//這是一個虛方法
virtual int write_row(uchar *buf __attribute__((unused)))
{
return HA_ERR_WRONG_COMMAND;
}
到底這話虛不虛,這次我親自調試一下給大家看看,證據先行哈。。。為了方便,我生成一條創表sql。
drop database if exists `datamip`;
create database `datamip`;
drop table if exists `datamip`.`customer`;
create table `datamip`.`customer` (
`customerID` int NOT NULL AUTO_INCREMENT COMMENT '自增主鍵',
`customerName` varchar(50) COMMENT '用戶姓名',
`email` varchar(50) COMMENT '郵箱地址',
`desc` varchar(50) COMMENT '描述',
primary key (`customerID`)
) ENGINE=InnoDB charset=utf8 collate=utf8_bin;
接下來,大家看仔細了,在源碼 int handler::ha_write_row(uchar *buf)
方法處下一個斷點,然後F5調試應用程序。
接下來可以執行insert操作,這地方會命中斷點的。
insert into `datamip`.`customer`(customerName,email,`desc`) values('mary','123456789@qq.com','vip');
可以看到,斷點命中了,然後進行單步調試,最終你會看到代碼會進入到 C:\2\mysql-5.7.12\storage\innobase\handler\ha_innodb.cc
中的 int ha_innobase::write_row
方法,如下圖:
然後找幾個局部變量和調用堆棧看看。。。
這就是我花了一下午的時間總結出的進坑出坑指南,希望能幫助大家節省時間,還是那句話,源碼面前,不談隱私,若還能進行調試,那一切皆為螻蟻!
本站聲明:網站內容來源於博客園,如有侵權,請聯繫我們,我們將及時處理
【其他文章推薦】
※USB CONNECTOR掌控什麼技術要點? 帶您認識其相關發展及效能
※台北網頁設計公司這麼多該如何選擇?
※智慧手機時代的來臨,RWD網頁設計為架站首選
※評比南投搬家公司費用收費行情懶人包大公開
※回頭車貨運收費標準
摘錄自2020年7月22日自由時報報導
義大利當地時間18日,一條抹香鯨在利帕里島(Lipari)附近海域被廢棄漁網纏住,義大利海警花了數天時間企圖割開漁網,但由於抹香鯨躁動,導致進度緩慢。
綜合外媒報導,一隻抹香鯨被發現受困於義大利利帕里島海域,牠被廢棄漁網困住無法游離,義大利海警獲報後,即刻出動潛水員救援,他們企圖割開漁網,但由於抹香鯨情緒不穩,相當躁動,令潛水員相當困擾,也因此把牠命為「Fury」(憤怒之意),潛水員花了3天時間才將部分漁網割下。
不料恢復行動力的「Fury」開始下潛失去蹤影,儘管纏在「Fury」身上的大部分漁網已經割開,不過牠的尾巴仍有魚網纏繞住,救難人員正積極尋找其下落。
本站聲明:網站內容來源環境資訊中心https://e-info.org.tw/,如有侵權,請聯繫我們,我們將及時處理
【其他文章推薦】
※為什麼 USB CONNECTOR 是電子產業重要的元件?
※網頁設計一頭霧水該從何著手呢? 台北網頁設計公司幫您輕鬆架站!
※台北網頁設計公司全省服務真心推薦
※想知道最厲害的網頁設計公司"嚨底家"!
※推薦評價好的iphone維修中心
我們可以將一些bean組件交由Spring管理,並且Spring支持單實例bean和多實例bean。我們自己寫的類,可以通過包掃描+標註註解(@Controller、@Servcie、@Repository、@Component)的形式將其註冊到IOC容器中,如果不是我們自己寫的類,比如,我們在項目中引入了一些第三方的類庫,此時,我們需要將這些第三方類庫中的類註冊到Spring容器中,該怎麼辦呢?此時,我們就可以使用@Bean和@Import註解將這些類快速的導入Spring容器中。接下來,我們來一起探討下如何使用@Import註解給容器中快速導入一個組件。
項目工程源碼已經提交到GitHub:https://github.com/sunshinelyz/spring-annotation
向Spring容器中註冊bean通常有以下幾種方式:
Spring 3.0之前,創建Bean可以通過xml配置文件與掃描特定包下面的類來將類注入到Spring IOC容器內。而在Spring 3.0之後提供了JavaConfig的方式,也就是將IOC容器里Bean的元信息以java代碼的方式進行描述。我們可以通過@Configuration與@Bean這兩個註解配合使用來將原來配置在xml文件里的bean通過java代碼的方式進行描述
@Import註解提供了@Bean註解的功能,同時還有xml配置文件里 標籤組織多個分散的xml文件的功能,當然在這裡是組織多個分散的@Configuration
先看一下@Import註解的源碼:
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Import {
/**
* {@link Configuration}, {@link ImportSelector}, {@link ImportBeanDefinitionRegistrar}
* or regular component classes to import.
*/
Class<?>[] value();
}
從源碼里可以看出@Import可以配合 Configuration
, ImportSelector
, ImportBeanDefinitionRegistrar
來使用,下面的or表示也可以把Import當成普通的Bean使用。
@Import只允許放到類上面,不能放到方法上。下面我們來看具體的使用方式。
@Import註解的三種用法主要包括:
注意:我們先來看第一種方法:直接填class數組的方式,其他的兩種方式我們後面繼續講。
首先,我們創建一個Department類,這個類是一個空類,沒有成員變量和方法,如下所示。
package io.mykit.spring.plugins.register.bean;
/**
* @author binghe
* @version 1.0.0
* @description 測試@Import註解的bean
*/
public class Department {
}
接下來,我們先在SpringBeanTest類中創建testAnnotationConfig7()方法,輸出Spring容器中所有的bean,來查看是否存在Department類對應的bean實例,以此來判斷Spring容器中是否註冊有Department類對應的bean實例。
@Test
public void testAnnotationConfig7(){
ApplicationContext context = new AnnotationConfigApplicationContext(PersonConfig2.class);
String[] names = context.getBeanDefinitionNames();
Arrays.stream(names).forEach(System.out::println);
}
運行SpringBeanTest類的testAnnotationConfig7()方法,輸出的結果信息如下所示。
org.springframework.context.annotation.internalConfigurationAnnotationProcessor
org.springframework.context.annotation.internalAutowiredAnnotationProcessor
org.springframework.context.annotation.internalCommonAnnotationProcessor
org.springframework.context.event.internalEventListenerProcessor
org.springframework.context.event.internalEventListenerFactory
personConfig2
person
binghe001
可以看到Spring容器中並沒有Department類對應的bean實例。
我們在PersonConfig2類上添加@Import註解,並將Department類標註到註解中,如下所示。
@Configuration
@Import(Department.class)
public class PersonConfig2 {
此時,我們再次運行SpringBeanTest類的testAnnotationConfig7()方法,輸出的結果信息如下所示。
org.springframework.context.annotation.internalConfigurationAnnotationProcessor
org.springframework.context.annotation.internalAutowiredAnnotationProcessor
org.springframework.context.annotation.internalCommonAnnotationProcessor
org.springframework.context.event.internalEventListenerProcessor
org.springframework.context.event.internalEventListenerFactory
personConfig2
io.mykit.spring.plugins.register.bean.Department
person
binghe001
可以看到,輸出結果中打印了io.mykit.spring.plugins.register.bean.Department,說明使用@Import導入bean時,id默認是組件的全類名。
@Import註解支持同時導入多個類,例如,我們再次創建一個Employee類,如下所示。
package io.mykit.spring.plugins.register.bean;
/**
* @author binghe
* @version 1.0.0
* @description 測試@Import註解的bean
*/
public class Employee {
}
接下來,我們也將Employee類添加到@Import註解中,如下所示。
@Configuration
@Import({Department.class, Employee.class})
public class PersonConfig2 {
此時,我們再次運行SpringBeanTest類的testAnnotationConfig7()方法,輸出的結果信息如下所示。
org.springframework.context.annotation.internalConfigurationAnnotationProcessor
org.springframework.context.annotation.internalAutowiredAnnotationProcessor
org.springframework.context.annotation.internalCommonAnnotationProcessor
org.springframework.context.event.internalEventListenerProcessor
org.springframework.context.event.internalEventListenerFactory
personConfig2
io.mykit.spring.plugins.register.bean.Department
io.mykit.spring.plugins.register.bean.Employee
person
binghe001
可以看到,結果信息中同時輸出了io.mykit.spring.plugins.register.bean.Department和io.mykit.spring.plugins.register.bean.Employee,說明Department類的bean實例和Employee類的bean實例都導入到Spring容器中了。
好了,咱們今天就聊到這兒吧!別忘了給個在看和轉發,讓更多的人看到,一起學習一起進步!!
項目工程源碼已經提交到GitHub:https://github.com/sunshinelyz/spring-annotation
如果覺得文章對你有點幫助,請微信搜索並關注「 冰河技術 」微信公眾號,跟冰河學習Spring註解驅動開發。公眾號回復“spring註解”關鍵字,領取Spring註解驅動開發核心知識圖,讓Spring註解驅動開發不再迷茫。
本站聲明:網站內容來源於博客園,如有侵權,請聯繫我們,我們將及時處理
【其他文章推薦】
※為什麼 USB CONNECTOR 是電子產業重要的元件?
※網頁設計一頭霧水該從何著手呢? 台北網頁設計公司幫您輕鬆架站!
※台北網頁設計公司全省服務真心推薦
※想知道最厲害的網頁設計公司"嚨底家"!
※推薦評價好的iphone維修中心
而依維柯的中控 則採用了深灰色的內飾配色,整體看起來略微有些沉悶。並且空調的出風口以及手套箱的設計相對過於緊湊,讓人感覺整个中控台略微有些凌亂。四輻式的方向盤造型也難以提升駕駛員的駕駛興趣。馬兒跑得快還要不吃草作為全新一代輕客的代表之作,光有光鮮的外表、時尚的造型可不夠,選擇這類車型的消費者們更為看重的必然是它們的內在能力。
拼家底誰更厚?
全順:全順在輕客領域摸爬滾打也有將近五十年歷史了。它的原型車可以追溯到1953年福特生產的一款輕型商用車FK1000,它於1961被稱作Ford Taunus Transit。1965年,福特汽車英國公司推出第一代福特Transit全順,迅速取得了輕型貨車領域的主導地位,並在此後一直霸佔着歐洲輕型客貨車銷量冠軍,成為了輕型客貨車的代名詞。
依維柯:作為歐洲的輕型商用車之一,依維柯在歐洲市場佔據很大的市場份額。在1975年的時候依維柯公司正式成立,1978年第一代依維柯Daily誕生。並且一直發展到今日,依維柯一共經歷了六次換代。
誰才是真正的“顏值帝”
外觀設計各花入各眼,但就目前的眼光來看,新全順外觀設計相比起老款可謂是翻天覆地,時尚動感的外型設計,微微收緊的車頭、熏黑的大燈以及一條筆直斜向上一直延伸到車尾的線條設計,彷彿讓新全順一躍跳出了輕客這個領域。
而依維柯則是傳統的造型設計,菱形的前大燈以及方方正正的車頭設計讓它很難與時尚設計扯上關係,保持了輕客一貫的傳統印象,但沒能給人眼前一亮的感覺。
內飾誰更前衛
新全順的內飾設計採用了福特最新家族的設計語言,非對稱式的中控設計,外加黑色內飾加銀色鍍鉻配色,整體顯得更有檔次感,中控面板和門把手對於細節的處理也非常細緻,非常符合新全順的車型定位。
而依維柯的中控 則採用了深灰色的內飾配色,整體看起來略微有些沉悶。並且空調的出風口以及手套箱的設計相對過於緊湊,讓人感覺整个中控台略微有些凌亂。四輻式的方向盤造型也難以提升駕駛員的駕駛興趣。
馬兒跑得快還要不吃草
作為全新一代輕客的代表之作,光有光鮮的外表、時尚的造型可不夠,選擇這類車型的消費者們更為看重的必然是它們的內在能力。就這方面來看,全順的表現還是極為優秀的。從動力上看新全順所搭載的2.0T柴油渦輪增壓發動機雖在排量上比起依維柯的2.5T渦輪發動機稍顯劣勢,但由於全順採用了新的渦輪技術使得在排量吃虧的情況下,依然在能在功率上追上對手,並且在扭矩上還略微有優勢。
江鈴福特-全順
南京依維柯-power Daily
【聽宣判pK結果】:兩位老對手的定位雖然相近,但是結合兩輛車的表現,新全順更加出色,在各個項目的表現上都要更勝一籌。而依維柯則保留了純粹的商用車氣息,缺乏了一點新時代的便利性以及通用性。本站聲明:網站內容來源於http://www.auto6s.com/,如有侵權,請聯繫我們,我們將及時處理
【其他文章推薦】
※為什麼 USB CONNECTOR 是電子產業重要的元件?
※網頁設計一頭霧水該從何著手呢? 台北網頁設計公司幫您輕鬆架站!
※台北網頁設計公司全省服務真心推薦
※想知道最厲害的網頁設計公司"嚨底家"!
※推薦評價好的iphone維修中心
在之前的幾章中,我們先搭建了一個項目骨架,又搭建了一個使用nacos的gateway網關項目,網關項目中並沒有配置太多的東西。現在我們就接着搭建在Spring Cloud 微服務中另一個重要的項目 – Spring boot admin.
Spring Boot Admin 用來監控基於Spring Boot的應用,在Spring Boot Actuator的基礎上提供了簡潔的可視化Web UI。Spring Boot Admin 提供了以下功能:
……
等一系列內容。
那麼,我們就來創建一個Spring Boot Admin 項目吧。
在manager 目錄下,創建一個 monitor目錄,並在monitor目錄下創建一個pom.xml 文件,添加以下內容:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<artifactId>monitor</artifactId>
<version>${revision}</version>
<packaging>jar</packaging>
<parent>
<artifactId>manager</artifactId>
<groupId>club.attachie</groupId>
<version>${revision}</version>
</parent>
</project>
在 manager/pom.xml 註冊我們新建的項目模塊:
<modules>
<module>gateway</module>
<module>monitor</module>
</modules>
在 monitor 創建如下目錄:
.
├── pom.xml
└── src
└── main
├── java
└── resources
在根目錄的pom.xml 添加 Spring Boot Admin 依賴:
先添加spring-boot-admin版本號變量:
<spring-boot-admin.version>2.2.3</spring-boot-admin.version>
並在dependencyManagement > dependencies 下添加:
<dependency>
<groupId>de.codecentric</groupId>
<artifactId>spring-boot-admin-starter-server</artifactId>
<version>${spring-boot-admin.version}</version>
</dependency>
在monitor/pom.xml文件中添加:
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>de.codecentric</groupId>
<artifactId>spring-boot-admin-starter-server</artifactId>
</dependency>
</dependencies>
運行
mvn clean install
檢查並刷mvn引用緩存。
創建MonitorApplication類:
package club.attachie.nature.monitor;
import de.codecentric.boot.admin.server.config.EnableAdminServer;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
@EnableAdminServer
public class MonitorApplication {
public static void main(String[] args) {
SpringApplication.run(MonitorApplication.class, args);
}
}
啟動后能看到如下界面:
在上一篇中,我們添加了Spring Cloud Gateway項目,到目前為止兩個項目之間完全割裂沒有關聯。在這一節,我們在兩者之間建立關聯。也就是說,將gateway 項目引入Spring Admin Boot監聽。
在 manager/gateway 的pom.xml 文件中加入如下引用:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
然後修改 gateway項目的啟動端口,在resources/bootstrap.yml 添加:
server:
port: 8070
在 monitor中加入nacos引用:
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
修改MonitorApplication 為:
package club.attachie.nature.monitor;
import de.codecentric.boot.admin.server.config.EnableAdminServer;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.context.config.annotation.RefreshScope;
@SpringBootApplication
@EnableAdminServer
@RefreshScope
public class MonitorApplication {
public static void main(String[] args) {
SpringApplication.run(MonitorApplication.class, args);
}
}
創建monitor項目的bootsrap.yml:
spring:
application:
name: monitor
cloud:
nacos:
discovery:
server-addr: 127.0.0.1:8848
關於這裏的配置 在上一篇 中有個錯誤,應該是 discovery > server-addr,不是 config > server-addr。兩者有區別,discovery表示設置nacos為服務發現中心,config表示nacos為配置中心。
啟動 gateway 項目和 monitor項目查看效果, 訪問 8080端口:
可以看到兩個應用可以被發現,如果沒有設置monitor項目把nacos當做服務發現中心,將無法獲取到具體在線的應用。點擊 gateway 進去后可以查看到:
我們搭建了一個Spring Boot Admin 項目作為一個監控系統,後續會在這裏添加更多的內容。
更多內容煩請關注我的博客《高先生小屋》
本站聲明:網站內容來源於博客園,如有侵權,請聯繫我們,我們將及時處理
【其他文章推薦】
※為什麼 USB CONNECTOR 是電子產業重要的元件?
※網頁設計一頭霧水該從何著手呢? 台北網頁設計公司幫您輕鬆架站!
※台北網頁設計公司全省服務真心推薦
※想知道最厲害的網頁設計公司"嚨底家"!
※推薦評價好的iphone維修中心
最不滿意的地方:起步有點肉,而且這個時候發動機聲音是比較大的。所以感覺上這個發動機實際動力還是比較一般的,而且發動機倉隔音也是比較一般。車主:老兵哥購買車型:北汽幻速S6 2017款 1。5T CVT樂享型裸車購買價:10。
前言
作為國內的造車大戶,北汽奉行着“多生孩兒多掙錢”的政策,有注重一般家用市場的北汽紳寶、有注重硬派SUV市場的北京汽車、還有着北汽幻速以及北汽比速這兩個入門品牌。那麼作為一個比較年輕的品牌,北汽幻速的口碑究竟怎樣呢?今天筆者就搜集了幾位北汽幻速S6車主的意見,這款7.98萬起售的緊湊型SUV有着該價位中不俗的競爭力。全系標配的是1.5T發動機,而且有着CVT變速箱作為自動擋的選擇。
那麼多孩子,打起群架肯定贏
北汽銀翔幻速S6
官方指導價:7.98-11.68萬
編者意見:
性價比較高,動力表現在同價位中表現比較優秀。不過全系沒能標配ESp車身穩定系統以及电子助力轉向比較可惜。
車主:BY2000
購買車型:北汽幻速S6 2017款 1.5T CVT尊享型
裸車購買價11.68 萬元
最滿意的地方:整體都比較滿意,但是最滿意的的是價格,性價比很高。能在這個價格買到這樣配置的緊湊型SUV還是不錯的,而且是渦輪增壓發動機。
最不滿意的地方:起步有點肉,而且這個時候發動機聲音是比較大的。所以感覺上這個發動機實際動力還是比較一般的,而且發動機倉隔音也是比較一般。
車主:老兵哥
購買車型:北汽幻速S6 2017款 1.5T CVT樂享型
裸車購買價:10.68 萬元
最滿意的地方:乘坐空間,沒有想到這個價格的車還能有着那麼大的空間,滿載的情況下也不是很擁擠。而且後備箱容積也是相當可觀,大天窗還有那麼多的配置,買這款車真的是比較值。
最不滿意的地方:裝配工藝有待加強,有些部分的縫隙是比較大的,就如尾門的縫隙,看着很掉價,而且方向盤塑料感太強了。
車主:smg20900
購買車型:北汽幻速S6 2017款 1.5T CVT尊享型
裸車購買價:10.68 萬元
最滿意的地方:外觀,看着更像是二十多萬的SUV。能給人更多的面子,而且在動力方面感覺還是不錯的,一直都可以維持在較低轉速,120km/h時速下轉速也只是2200rpm左右,這個是最為滿意的,所以綜合油耗上也是9L左右,對於一款SUV來說是滿意了。
最不滿意的地方:儲物空間實在是少得可憐,中間只有一個杯架,不夠用。其次是噪音的問題,不過對於如此便宜的車來說,還是可以接受的。
編者總結:
北汽雖然是個歷史悠長的品牌,但事實基本是為別人“代工”,自身在工藝方面以及控製成本方面還是需要向合資學習,所以在做工以及隔音用料上表現一般。不過在主要的發動機上表現卻是相當不錯,雖然渦輪遲滯現象還是有的,但是油耗表現卻是令人信服的。本站聲明:網站內容來源於http://www.auto6s.com/,如有侵權,請聯繫我們,我們將及時處理
【其他文章推薦】
※為什麼 USB CONNECTOR 是電子產業重要的元件?
※網頁設計一頭霧水該從何著手呢? 台北網頁設計公司幫您輕鬆架站!
※台北網頁設計公司全省服務真心推薦
※想知道最厲害的網頁設計公司"嚨底家"!
※推薦評價好的iphone維修中心
this 是 js 里繞不開的話題,也是非常容易混淆的概念,今天試着把它理一理。
this 在非嚴格模式下,總是指向一個對象,在嚴格模式下可以是任意值,本文僅考慮非嚴格模式。記住它總是指向一個對象對於理解它的意義很重要。this 在實際使用中,大致分為以下幾種情況:
1. 函數作為對象的方法調用時,this 指向調用該函數的對象
var obj = { name: 'jack', getName: function() { console.log(this === obj) // true console.log(this.name) // jack } } obj.getName()
這個應該很好理解,不多說了。
2. 函數作為普通函數被調用時,this 指向全局對象。在瀏覽器中,全局對象是window。
var name = 'global' function getName() { console.log(this === window) // true console.log(this.name) // global }
getName()
我的理解是上面的代碼可以改寫為
window.name = 'global' window.getName = function() { console.log(this === window) // true console.log(this.name) // global } window.getName()
這樣其實與情況1是一樣的,相當於函數作為對象的方法調用,只不過這裏的對象是全局對象。
《Javascript 設計模式與開發實踐》一書中有個例子如下:
window.name = 'globalName'; var myObject = { name: 'seven', getName: function(){ return this.name } } var getName = myObject.getName console.log(getName()) // globalName
getName 是定義在myObject 對象中的方法,在調用getName 方法時,打印出的卻是全局對象的name,而不是myObject對象的name,這再次證明了 this 並非指向函數被聲明時的環境對象,而是指向函數被調用時的環境對象。
3. 函數作為構造函數調用時,指向構造出的新對象
function Person(name) { this.name = name } var jack = new Person('Jack') console.log(jack.name) // Jack
var rose = new Person('Rose')
console.log(rose.name) // Rose
這裏創建了兩個不同名字的對象,打印出的name也是不一樣的,說明構造函數的 this 會根據創建對象的不同而變化。需要注意的是,如果構造函數里返回了一個Object類型的對象,那麼this會指向這個對象,而不是利用構造函數創建出的對象。我們在構造函數一章里也提到過,new 操作符所做的最後一步就是返回新對象,而如果我們顯式地返回一個對象,就會覆蓋這步操作,this也就不再指向新對象。
4. 函數作為事件處理函數調用時,指向觸發事件的元素
document.getElementById("myBtn").addEventListener("click", function(e){ console.log(this === e.currentTarget) // true });
5. 箭頭函數
由於箭頭函數沒有this,它的 this 是繼承父執行上下文裏面的 this。執行上下文後面再討論,現在只要知道簡單對象(非函數)是沒有執行上下文的。
var obj = { name: 'obj', getName: function() {
console.log(this) // 執行上下文里的 this return (()=>{ console.log(this.name) }) } } var fn = obj.getName() fn() // obj
按照情況2來處理的話,this 指向全局對象,應該輸出 undefined,結果並不是。與普通函數不同,箭頭函數的 this 是在函數被聲明時決定的,而不是函數被調用時。在這裏,父執行上下文是 getName 函數,也就繼承了 getName 的 this,即 obj。
利用 bind、apply、call 改變 this 指向
bind、apply、call 都是定義在 Function 原型對象上的方法,所有函數對象都能繼承這個方法,三者都能用來改變 this 指向,我們來看看它們的聯繫與區別。
function fn() { console.log(this.name) } // bind var bindfn = fn.bind({name: 'bind'}) bindfn() // bind // apply fn.apply({name: 'apply'}) // apply // call fn.call({name: 'call'}) // call
我們定義了一個函數fn,然後分別調用了它的 bind、apply、call 方法,並傳入一個對象參數,通過打印出的內容可以看到 this 被綁定到了參數對象上。bind 似乎有些不同,多了一步 bindfn() 調用,這是因為 bind 方法返回的是一個函數,不會立即執行,而調用 apply 和 call 方法會立即執行。
下面再來看一下 fn 函數存在參數的情況:
function fn(a, b, c) { console.log(a, b, c) } var bindfn = fn.bind(null, 'bind'); bindfn('A', 'B', 'C'); // bind A B fn.apply(null, ['apply', 'A']) // apply A undefined fn.call(null, 'call', 'A'); // bind A undefined
bindfn 打印出的結果是fn調用bind方法時的傳遞的參數加上bindfn傳遞的參數,參數 ‘C’ 被捨棄掉了。調用 apply 和 call 方法打印出的則是傳遞給它們的參數,不一樣的是,apply 的參數是一個數組(或類數組),call 則是把參數依次傳入函數。這時候再看它們的定義應該會好理解很多:
bind() 方法創建一個新的函數,在 bind() 被調用時,這個新函數的 this 被指定為 bind() 的第一個參數,而其餘參數將作為新函數的參數,供調用時使用。
apply() 方法調用一個具有給定 this 值的函數,以及作為一個數組(或類數組對象)提供的參數。
call() 方法使用一個指定的 this 值和單獨給出的一個或多個參數來調用一個函數。
我們可以利用它們來借用其他對象的方法。已知函數的參數列表 arguments 是一個類數組對象,比如上例中函數 fn 的參數 a, b, c,因為它不是一個真正的數組,不能調用數組方法,這時借用 apply/call 方法(bind 也可以,就是用得比較少)將 this 指向 arguments 就能借用數組方法:
(function(){ Array.prototype.push.call(arguments, 'c') console.log(arguments) // ['a', 'b', 'c'] })('a','b')
值得一提的是,push 方法並不是只有數組才能調用,一個對象只要滿足1.可讀寫 length 屬性;2.對象本身可存取屬性. 就可以利用 call / apply 調用 push 方法。
參考:
《Javascript 設計模式與開發實踐》
https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Operators/this
http://www.imooc.com/article/80117
https://blog.csdn.net/weixin_42519137/article/details/88053339
本站聲明:網站內容來源於博客園,如有侵權,請聯繫我們,我們將及時處理
【其他文章推薦】
※為什麼 USB CONNECTOR 是電子產業重要的元件?
※網頁設計一頭霧水該從何著手呢? 台北網頁設計公司幫您輕鬆架站!
※台北網頁設計公司全省服務真心推薦
※想知道最厲害的網頁設計公司"嚨底家"!
※推薦評價好的iphone維修中心
我們要清楚現在的情況.
現在我們已經調用了SqlSessionFactoryBuilder
的build方法生成了SqlSessionFactory
對象.
但是如標題所說,要想生成sqlsession
還要另一步SqlSessionFactory
調用openSession()
方法生成sqlsession
;
這就要從上一部分代碼講起
上文講到
我們創建的實際上是一個叫做DefaultSqlSessionFactory
的類,實際上他是一個SqlSessionFactory
接口(沒錯,這玩應是接口)的實現類.
既然sqlsession是由opensession產生的,那我們就先看這個方法.
說一嘴題外話就是自動提交也是在這個部分設置的,下面是如果你設置了autocommit的情況.
public SqlSession openSession(boolean autoCommit) {
//this.configuration.getDefaultExecutorType()值為 ExecutorType.SIMPLE;
return this.openSessionFromDataSource(this.configuration.getDefaultExecutorType(), (TransactionIsolationLevel)null, autoCommit);
}
參數中 configuration 獲取了默認的執行器 “SIMPLE”.
DefaultSqlSessionFactory
類調用了一個同一個類中openSessionFromDataSource
方法.
在這個類中是如下執行流程
所要知道的一部分知識.
environments運行環境
MyBatis 核心配置綜述之 Configuration詳解
其實就是數據庫連接那個部分.
private SqlSession openSessionFromDataSource(ExecutorType execType, TransactionIsolationLevel level, boolean autoCommit) {
Transaction tx = null;
try {
//從configuration對象中得到環境配置的對象
final Environment environment = configuration.getEnvironment();
//這個對象被用來創建一個事務工廠->一號分支
final TransactionFactory transactionFactory = getTransactionFactoryFromEnvironment(environment);
//事務工廠創建一個事務對象->二號分支
tx = transactionFactory.newTransaction(environment.getDataSource(), level, autoCommit);
//而 configurationye 則會根據事務對象和執行器類型創建一個執行器。
->三號分支
final Executor executor = configuration.newExecutor(tx, execType);
//返回一個默認的DefaultSqlSession對象
->四號分支
return new DefaultSqlSession(configuration, executor, autoCommit);
} catch (Exception e) {
closeTransaction(tx); // may have fetched a connection so lets call close()
throw ExceptionFactory.wrapException("Error opening session. Cause: " + e, e);
} finally {
ErrorContext.instance().reset();
}
}
現在我們要從一號分支開始
final TransactionFactory transactionFactory = getTransactionFactoryFromEnvironment(environment);
這個代碼如下:
我們發現有兩種可能性.
如果傳進來的值沒有設置 標籤那麼他會執行 ManagedTransactionFactory()
而反之則會執行 environment.getTransactionFactory()
這兩者產生的對象都實現了 TransactionFactory
接口.
這裏ManagedTransactionFactory()
是沒有標籤時生成的對象.其核心就是一句
private boolean closeConnection = true;
的屬性.
我們不必過於關注這個部分.
private TransactionFactory getTransactionFactoryFromEnvironment(Environment environment) {
if (environment == null || environment.getTransactionFactory() == null) {
//如果沒有目標標籤
return new ManagedTransactionFactory();
}
//如果有目標標籤
return environment.getTransactionFactory();
}
environment.getTransactionFactory()
產生的東西才是重點.
調用環境對象的getTransactionFactory
方法,該方法和我們配置的一樣返回了一個 JdbcTransactionFactory
,而實際上,TransactionFactory
只有2個實現類,一個是 ManagedTransactionFactory
(沒有標籤時返回的),一個是 JdbcTransactionFactory
(有標籤時返回的)。
至此一號分支結束,從此看來,一號分支實際上是將environment對象包裝成一個工廠對象.
請返回一號分支之前部分繼續.
tx = transactionFactory.newTransaction(environment.getDataSource(), level, autoCommit);
我們回到openSessionFromDataSource
方法,獲取了 JdbcTransactionFactory
后,調用 JdbcTransactionFactory
的newTransaction
方法創建一個事務對象.
當然因為代碼中採用TransactionFactory
接口作為聲明對象.所以無論分之一傳回來的是哪個工廠對象.在分支二中都可以執行.
我們先講 JdbcTransactionFactory
的情況.
分支二中調用的是這個newTransaction
方法.(還有一個重載的)
public Transaction newTransaction(Connection conn) {
return new JdbcTransaction(conn);
}
這就到了另一個類中JdbcTransaction
中.
我刪掉其中的實現代碼
public class JdbcTransaction implements Transaction {
private static final Log log = LogFactory.getLog(JdbcTransaction.class);
protected Connection connection;
protected DataSource dataSource;
protected TransactionIsolationLevel level;
protected boolean autoCommmit;
public JdbcTransaction(DataSource ds, TransactionIsolationLevel desiredLevel, boolean desiredAutoCommit) {
dataSource = ds;
level = desiredLevel;
autoCommmit = desiredAutoCommit;
}
public JdbcTransaction(Connection connection) {
this.connection = connection;
}
public Connection getConnection() throws SQLException {
}
public void commit() throws SQLException {
}
public void rollback() throws SQLException {
}
public void close() throws SQLException {
}
protected void setDesiredAutoCommit(boolean desiredAutoCommit) {
}
protected void resetAutoCommit() {
}
protected void openConnection() throws SQLException {
}
}
其實只要看了代碼你就會發現,這個類中的方法,和我們調用session的方法高度重合.比如commit,rollback等等.而且還能設置事務的隔離級別
所以我們有理由認為,這個類就是對jdbc連接部分的封裝.
總結
至此分支二結束,我們對於 標籤在xml中的存在情況,會返回兩種截然不同對象.一種是作為jdbc連接封裝的 JdbcTransaction
對象.另一個則是 ManagedTransaction
對象(這個沒講….)
第三分支我們將回到Configuration
對象.
法此時已經創建好事務對象。接下來將事務對象執行器作為參數執行 configuration 的 newExecutor 方法來獲取一個 執行器類。我們看看該方法實現:
首先第一句將判斷是否傳入了一個excutorType參數,如果沒有就用默認的參數.
也就是 ExecutorType.SIMPLE(前面出現過),然後根據執行的類型來創建不同的執行器,默認是 SimpleExecutor 執行器.
Mybatis有三種基本的Executor執行器:
SimpleExecutor:每執行一次update或select,就開啟一個Statement對象,用完立刻關閉Statement對象。
ReuseExecutor:執行update或select,以sql作為key查找Statement對象,存在就使用,不存在就創建,用完后,不關閉Statement對象,而是放置於Map<String, Statement>內,供下一次使用。簡言之,就是重複使用Statement對象。
BatchExecutor:執行update(沒有select,JDBC批處理不支持select),將所有sql都添加到批處理中(addBatch()),等待統一執行(executeBatch()),它緩存了多個Statement對象,每個Statement對象都是addBatch()完畢后,等待逐一執行executeBatch()批處理。與JDBC批處理相同。
作用範圍:Executor的這些特點,都嚴格限制在SqlSession生命周期範圍內。
然後我們看下一句部分
Executor executor;
//看看上文.這是根據傳入的內容不同,最終結果是
if (ExecutorType.BATCH == executorType) {
executor = new BatchExecutor(this, transaction);
} else if (ExecutorType.REUSE == executorType) {
executor = new ReuseExecutor(this, transaction);
} else {
executor = new SimpleExecutor(this, transaction);
}
我們先將 BatchExecutor執行器.
該類包裝了事務對象,延遲加載的隊列,本地緩存,永久緩存,配置對象,還包裝了自己。
傳入的兩個參數分別為存儲了配置信息的Configuration對象,以及封裝了jdbc中連接數據庫部分代碼的
JdbcTransaction
對象.
回到 newExecutor 方法,判斷是否使用緩存,默認是true, 則將剛剛的執行器包裝到新的 CachingExecutor 緩存執行器中。最後將執行器添加到所有的攔截器中(如果配置了話),我們這裏沒有配置。
到此分支三結束
總結:
我們從用從分支二得到的對象,構建了一個執行器.這個執行對象,包括事務對象(即連jdbc連接部分的控制封裝.JdbcTransaction
),延遲加載的隊列,本地緩存,永久緩存,配置對象(Configuration),還包裝了自己。
我們已經有了執行器,此時創建 DefaultSqlSession 對象,攜帶 configuration, executor, autoCommit 三個參數,該構造器就是簡單的賦值過程。我們有必要看看該類的結構:
該類包含了常用的所有方法,包括事務方法,可以說,該類封裝了執行器和事務類。而執行器才是具體的執行工作人員。
至此,我們已經完成了 SqlSession 的創建過程。
本站聲明:網站內容來源於博客園,如有侵權,請聯繫我們,我們將及時處理
【其他文章推薦】
※為什麼 USB CONNECTOR 是電子產業重要的元件?
※網頁設計一頭霧水該從何著手呢? 台北網頁設計公司幫您輕鬆架站!
※台北網頁設計公司全省服務真心推薦
※想知道最厲害的網頁設計公司"嚨底家"!
※推薦評價好的iphone維修中心
2016年沃爾沃汽車進一步確立了在自動駕駛、電氣化及安全領域的領先地位,建立了新的商業聯盟,並不斷推出全新的產品,打造立足全球的生產製造基地。2016年沃爾沃汽車斥資5億美元在美國南卡羅來納州興建工廠,將生產基於SpA架構的車型,初期將聘用2,000餘名員工。
沃爾沃汽車集團近日發布2016年銷售業績显示,2016年沃爾沃汽車全球共實現銷量534,332輛,同比增長6.2%,連續三年創銷量紀錄。2016年沃爾沃汽車在全球各大市場銷量齊頭並進,在中國和北美兩大市場均實現了兩位數增幅,西歐市場表現強勁,沃爾沃汽車全球復興第二階段持續加速。
S90
沃爾沃全新90系車型2016年銷量飄紅,其中XC90車型銷量較2015年激增了125%,印證了沃爾沃全新的設計語言及創新科技在全球取得成功,為未來沃爾沃全新車型的上市,打下堅實的基礎。同時,沃爾沃XC60車型年銷量達到161,092輛,自2008年投放市場以來,連續九年屢創銷量紀錄。
XC90
2016年沃爾沃汽車在中國市場銷量達90,930輛,同比增長11.5%。中國依然是沃爾沃汽車全球最大單一市場。其中,國產沃爾沃XC60和S60L是沃爾沃汽車在中國市場最暢銷的車型。
沃爾沃汽車2016年在美國市場銷量增幅達18.1%,是美國增速最快的豪華汽車品牌之一,實現年銷量82,726輛。其中沃爾沃XC90和XC60最受美國消費者歡迎,市場表現出眾。得益於德國、英國、法國和意大利等主要市場強勁業績的推動,2016年沃爾沃汽車在西歐銷量增長4.1%,達到206,144輛。
沃爾沃汽車2016年實現銷量破紀錄的同時,通過全球復興和品牌重新定位持續強化與其他豪華品牌的競爭優勢。2016年沃爾沃汽車進一步確立了在自動駕駛、電氣化及安全領域的領先地位,建立了新的商業聯盟,並不斷推出全新的產品,打造立足全球的生產製造基地。
2016年沃爾沃汽車斥資5億美元在美國南卡羅來納州興建工廠,將生產基於SpA架構的車型,初期將聘用2,000餘名員工。2016年沃爾沃汽車發布了中國製造戰略,在提升產能的同時,將中國打造成了面向全球市場的生產和出口基地。沃爾沃大慶工廠生產旗艦級全新S90系家族,成都工廠生產現款60系及未來全新60系車型,基於CMA架構的全新40系車型正在規劃中,將在距上海以南350公里的路橋工廠投產。
2016年9月,隨着沃爾沃全新V90 Cross Country旅行越界車的上市,沃爾沃全新90系車型已全部完成換代。其中XC90車型更是榮獲120多個國際大獎,充分展現了沃爾沃全新SpA架構在設計、技術等方面的領先優勢。
V90 Cross Country
未來幾年,沃爾沃汽車將以每年兩款全新車型的速度完成全部產品換代。2017年將推出基於SpA架構的全新XC60車型,以及基於CMA架構的首款40系產品——全新XC40車型;在新能源領域,2016年沃爾沃汽車發布了全方位的電氣化戰略,將在全系車型中引入插電式混合動力系統,並在2019年之前推出首款純電動車,到2025年將實現新能源車型累計銷量100萬輛。
2016年沃爾沃汽車與優步(Uber)公司攜手合作開發自動駕駛技術,與瑞典奧托立夫公司(Autoliv)合作建立了合資公司——Zenuity,致力於設計和開發自動駕駛軟件及高級駕駛輔助系統,將為快速發展的全球市場提供自動駕駛軟件等服務。這也是豪華汽車品牌首次與一線供應商聯手開發相關技術,將為汽車行業帶來重大變革。
2017年沃爾沃汽車將在瑞典總部哥德堡進一步推動Drive Me自動駕駛測試項目。作為目前全球最先進、最前沿的自動駕駛測試項目,沃爾沃汽車將提供100輛XC90自動駕駛汽車用於普通居民在真實的日常環境中出行使用。未來,沃爾沃汽車還將在中國與英國啟動DriveMe自動駕駛測試項目。
隨着全球復興進度的加快及全新商業模式的拓展,沃爾沃汽車不僅是全球豪華汽車製造商,還將成為了一家全球高端移動出行公司。本站聲明:網站內容來源於http://www.auto6s.com/,如有侵權,請聯繫我們,我們將及時處理
【其他文章推薦】
※為什麼 USB CONNECTOR 是電子產業重要的元件?
※網頁設計一頭霧水該從何著手呢? 台北網頁設計公司幫您輕鬆架站!
※台北網頁設計公司全省服務真心推薦
※想知道最厲害的網頁設計公司"嚨底家"!
※推薦評價好的iphone維修中心