您現在的位置是:首頁 > 網路遊戲首頁網路遊戲
Java開發面試過程中的問題整理二
- 2022-04-28
怎麼獲取屬性上的註解
接著上文
Java開發面試過程中的問題整理一
講解的Java基礎和前端框架,今天來說說後端技術。
三、後端技術
1、Spring
(1)Spring中IOC和AOP的應用場景。
AOP:面向切面程式設計
。可以運用在日誌,事務和異常處理等。如果不使用aop,那麼就必須在每個類和方法中去實現它們。程式碼糾纏在一起。每個類和方法中都包含日誌、事務或者異常處理甚至是業務邏輯。在一個這樣的方法中,很難分清程式碼中實際做的是什麼處理。AOP 所做的就是將所有散落各處的事務程式碼集中到一個事務切面中。
AOP日誌處理:使用Aop在介面方法上插入一行自定義的切面註解類,在切面處理類中可以記錄介面名稱、請求引數、請求ip、請求url、請求時間、響應引數、響應狀態、呼叫時長等;
AOP事務處理:Spring在方法訪問資料庫之前,自動開啟事務,當訪問資料庫結束之後,自動提交/回滾事務;
AOP異常處理:自定義開啟環繞通知,一旦執行介面報錯,環繞通知捕獲異常跳轉異常處理頁面。
IOC就是Inversion of Control,即控制反轉,又稱依賴注入
。它不是什麼技術,而是一種設計思想。在Java開發中,傳統的建立物件的方法是直接透過 new 關鍵字(之前我們透過 “類名 物件名 = new 類名( )”的方式進行物件的建立,也就是說我們的程式負責物件的建立,控制了它是否被建立這件事情,這就叫做控制),而 spring 則是透過 IOC 容器來建立物件,也就是說我們將建立物件的控制權交給了 IOC 容器。這稱為控制反轉。
概括的說就是:IOC 讓程式設計師不再關注怎麼去建立物件,而是關注於物件建立之後的操作,把物件的建立、初始化、銷燬等工作交給spring容器來做。
舉個例子:梳理這個問題在各種社會形態裡如何解決:一個人(Java例項,呼叫者)需要一把斧子(Java例項,被呼叫者)
① 原始社會里,幾乎沒有社會分工。需要斧子的人(呼叫者)只能自己去磨一把斧子(被呼叫者)。對應的情形為:Java程式裡的呼叫者自己建立被呼叫者。
②進入工業社會,工廠出現。斧子不再由普通人完成,而在工廠裡被生產出來,此時需要斧子的人(呼叫者)找到工廠,購買斧子,無須關心斧子的製造過程。對應Java程式的簡單工廠的設計模式。
③進入“按需分配”社會,需要斧子的人不需要找到工廠,坐在家裡發出一個簡單指令:需要斧子。斧子就自然出現在他面前。對應Spring的依賴注入。
第一種情況下,Java例項的呼叫者建立被呼叫的Java例項,必然要求被呼叫的Java類出現在呼叫者的程式碼裡。無法實現二者之間的松耦合。
第二種情況下,呼叫者無須關心被呼叫者具體實現過程,只需要找到符合某種標準(介面)的例項,即可使用。此時呼叫的程式碼面向介面程式設計,可以讓呼叫者和被呼叫者解耦,這也是工廠模式大量使用的原因。但呼叫者需要自己定位工廠,呼叫者與特定工廠耦合在一起。
第三種情況下,呼叫者無須自己定位工廠,程式執行到需要被呼叫者時,系統自動提供被呼叫者例項。事實上,呼叫者和被呼叫者都處於Spring的管理下,二者之間的依賴關係由Spring提供。
生活中這種例子比比皆是,支付寶在整個淘寶體系裡就是龐大的ioc容器,交易雙方之外的第三方資金管理中心。
(2)Spring依賴注入的方式有哪些?
【set設值注入、建構函式注入、spring註解注入】
Spring IOC既可以透過XML的形式進行bean與依賴注入配置,也可以透過註解的方式。(在springmvc中,我們一般使用xml進行裝配,而springboot使用全註解的形式)
①透過XML的形式進行bean與依賴注入(
通常有兩種: 設值注入、構造注入
)
設值注入就是指要被注入的類中定義有一個setter()方法,並在引數中定義需要注入的物件。
構造注入就是指要被注入的類中宣告一個構造方法,並在此方法的引數中定義要注入的物件。
②註解的方式:
註解包含三部分:
| 元件型別註解——聲明當前類的功能與職責
|| 自動裝配註解——根據屬性特徵自動注入物件
||| 元資料註解——更細化的輔助IoC容器管理物件的註解
A、四種元件型別註解
@Component:元件註解,通用註解,該註解描述的類將被IoC容器管理並例項化
@Controller:語義註解,說明當前類是MVC應用中的控制類
@Service:語義註解,說明當前類是Service業務服務類
@Repository:語義註解,說明當前類作用於業務持久層,通常描述對應Dao類
此外,在使用四種元件型別的註解時,必須開啟元件掃描,詳細配置如下:
B、兩類自動裝配註解
按型別裝配
@Autowired
@Inject
按名稱裝配
@Named
@Resource
優先設定name屬性,若未包含name屬性,會按照@Autowired注入
C、元資料註解
@Primary——按型別裝配時出現多個相同型別的物件,擁有此註解物件優先被注入
@PostContruct:相當於init-method
@PreDestory:相當於destory——method
@Scope:設定物件Scope屬性
@Value:為屬性注入靜態資料
(3)為什麼非使用依賴注入,我要用到一個其他物件時,new一個怎麼就不好了?
本質上都是建立物件,最大的區別還是生命週期的管理以及複雜依賴的處理。
①、生命週期
比如一個類或者介面全程只要一個例項,用依賴注入的話只需要註冊成單例及可,如果自己例項化的話你需要擼一個單機模式(餓漢、懶漢、執行緒安全等模式)的類,併發下還要考慮執行緒安全。
②、複雜依賴
如果這個類或者介面不依賴其他的類或者介面差異不明顯,如果依賴的類比較多的情況下(A依賴B,B又依賴C,C又依賴D,D又依賴其他)自己例項化會很麻煩。要建立A, 要先B、C、D先new一遍再new A。用ioc就快多了,A(B b),其他自動建立,是不是快多了。
總結:在程式中如果不是必須同一個物件多個例項時,也就是一個物件只是在某個地方使用一下時new一下,依賴注入就比new一個物件更好,因為new一個物件必選面臨頻繁建立和銷燬記憶體例項物件的問題。而ioc管控下例項物件都是單例模式的,就是在程式執行時始終只有一個物件例項生成不需要頻繁建立和銷燬,也因為在記憶體中只有一個例項物件,減少記憶體開銷。
(4)描述一下DispatcherServlet的工作流程?
(5)SpringMVC如何區分控制器返回的是頁面還是資料(比如JSON格式的資料)?
使用@ResponseBody註解,該註解用於將Controller方法返回的物件,透過適當的HttpMessageConverter轉化為指定格式後,寫入到Response物件的body資料區。
使用時機:返回的資料不是html標籤的頁面,而是其他某種格式的資料時(如json,xml等)(如果是在程式中返回的html頁面程式碼,也可以使用@ResponseBody,在HttpServletResponse寫入,設定ContentType為text/html)
(6)Spring全家桶有哪些?
Spring、Spring MVC、Spring Boot、Spring Cloud 、 Spring Security 、Spring Data。
(7)Spring普通類與工具類如何呼叫service層方法,為什麼不能直接使用註解呼叫?
Spring中的Service不是你想new就能new的,因為透過new例項化的物件脫離了Spring容器的管理,獲取不到註解的屬性值,所以會是null,就算呼叫service的類中有@Component註解加入了Spring容器管理,也還是null。
處理辦法:新建SpringContextUtil類,在application。xml配置SpringContextUtil,最後使用
DictService dictService = (DictService) SpringContextUtil。getBean(“dictService”);
2、Springboot
(1) SpringBoot中如何進行單元測試?
匯入spring-boot-starter-test依賴。測試類使用註解@SpringBootTest,測試的方法上加@Test註解。
(2) SpringBootApplication註解的作用。
@SpringBootApplication註解是一個組合註解,@SpringBootApplication註解的原始碼我們發現,它是由ComponentScan、SpringBootConfiguration、EnableAutoConfiguration等註解組合而成:
(3) 在一個Springboot+mybatis+mysql+oracle+redis+aop功能的專案中,在pom.xml中需要引入哪些jar包依賴?
進一步提問:以redis為例,springboot 1.x與springboot 2.x引入的jar包有何不同?
在 springboot 1。5。x版本的預設的Redis客戶端是Jedis實現的,springboot 2。x版本中預設客戶端是用lettuce實現的。
3、SpringCloud
(1)springCloud的核心元件有哪些,解決什麼問題?
Eureka(註冊中心)
每個微服務都有一個EurekaClient元件,專門負責將這個服務的資訊註冊到EurekaServer中,也就是告訴EurekaServer,自己在哪臺機器上,監聽著哪個埠。而EurekaServer是一個註冊中心,裡面有一個登錄檔,儲存了各服務所在的機器和埠號。
Feign(REST客戶端)
Feign是一個宣告式REST客戶端,主要是為了簡便服務呼叫,更快捷、優雅地呼叫HTTPAPI。主要是實現原理是用動態代理,你要是呼叫哪個介面,本質就是呼叫Feign建立的動態代理。
Ribbon(負載均衡)
Ribbon的作用是負載均衡,會幫你在每次請求時選擇一臺機器,均勻的把請求分發到各個機器上,預設使用的最經典的RoundRobin輪詢演算法(如果發起10次請求,那就先讓你請求第1臺機器、然後是第2臺機器、第3臺機器,接著再來—個迴圈,第1臺機器、第2臺機器。。。以此類推)
Hystrix(熔斷器)
微服務框架是許多服務互相呼叫的,要是不做任何保護的話,某一個服務掛了,就會引起連鎖反應,導致別的服務也掛。Hystrix是隔離、熔斷以及降級的一個框架。如果呼叫某服務報錯或者掛了,就對該服務熔斷,在5分鐘內請求此服務直接就返回一個預設值,不需要每次都卡幾秒,這個過程,就是所謂的熔斷。但是熔斷了之後就會少呼叫一個服務,此時需要做下標記,標記本來需要做什麼業務,但是因為服務掛了,暫時沒有做,等熔斷的服務恢復了,就可以手工處理這些業務。這個過程,就是所謂的降級。
Zuul(服務閘道器)
Zuul微服務閘道器,負責網路路由。假設你後臺部署了幾百個服務,現在有個前端兄弟要來呼叫這些服務,難不成你讓他把所有服務的名稱和地址全部記住,這是不現實的,所以一般微服務架構中都必然會設計一個閘道器,所有請求都往閘道器走,閘道器會根據請求中的一些特徵,將請求轉發給後端的各個服務。而且有一個閘道器之後,還有很多好處,比如可以做統一的降級、限流、認證授權、安全,等等。
總結步驟:①服務註冊—》②服務發現—》③負載均衡—》④服務呼叫—》⑤隔離、熔斷與降級—》⑥閘道器路由
流程說明
:各個服務啟動時,Eureka Client都會將服務註冊到Eureka Server,並且Eureka Client還可以反過來從Eureka Server拉取登錄檔,從而知道其他服務在哪裡。服務間發起請求的時候,基於Ribbon做負載均衡,從一個服務的多臺機器中選擇一臺。基於Feign的動態代理機制,根據註解和選擇的機器,拼接請求URL地址,發起請求。發起請求是透過Hystrix的執行緒池來走的,不同的服務走不同的執行緒池,實現了不同服務呼叫的隔離,避免了服務雪崩的問題。如果前端、移動端要呼叫後端系統,統一從Zuul閘道器進入,由Zuul閘道器轉發請求給對應的服務。
(2)SpringCloud和Dubbo兩種微服務架構有何區別?
Dubbo的定位始終是一款RPC框架,而SpringCloud的目標是微服務架構下的一站式解決方案。如果非要比較的話,Dubbo可以類比到NetflixOSS技術棧,而SpringCloud集成了NetflixOSS作為分散式服務治理解決方案,但除此之外SpringCloud還提供了配置、訊息、安全、呼叫鏈跟蹤等分散式問題解決方案。
(2)SpringBoot和SpringCloud 側重點分別在哪些方面?
SpringBoot是Spring的一套快速配置腳手架,可以基於SpringBoot快速開發單個微服務,SpringCloud是一個基於SpringBoot實現的雲應用開發工具;
SpringBoot專注於快速、方便整合的單個微服務個體,SpringCloud關注全域性的服務治理框架;
SpringBoot使用了預設大於配置的理念,很多整合方案已經幫你選擇好了,能不配置就不配置,SpringCloud很大的一部分是基於SpringBoot來實現。SpringBoot可以離開SpringCloud獨立使用開發專案,但是SpringCloud離不開SpringBoot,屬於依賴的關係。
(4)springcloud如何實現服務的註冊和呼叫?
①服務釋出時,指定對應的服務名(服務名包括了IP地址和埠),將服務註冊到註冊中心(eureka 或者zookeeper)
②註冊中心加@EnableEurekaServer,服務用@EnableDiscoveryClient,然後用ribbon或feign進行服務直接的呼叫發現。(這一過程是springcloud自動實現 只需要在main方法新增@EnableDisscoveryClient。同一個服務修改埠就可以啟動多個例項)
4、mybatis
(1)Mybatis中mapper.xml對映檔案,通常都會寫一個Mapper介面與之對應,這個Mapper層介面是怎麼能夠找到指定xml下的方法的?
Mapper介面是沒有實現類的,當呼叫介面方法時,介面全限名(就是對映檔案中的namespace的值)+方法名拼接字串作為key值,可唯一定位一個MapperStatement。在Mybatis中,每一個
(2)Mybatis的xml對映檔案中,不同的xml對映檔案,id是否可以重複?
不同的Xml對映檔案,如果配置了namespace,那麼id可以重複;如果沒有配置namespace,那麼id不能重複;原因就是namespace+id是作為Map
(3)Mybatis中使用MySQL和Oracle分頁的區別
MySQL分頁:(利用LIMIT關鍵字)計算引數為開始序號(startNum),要查的總條數(totalNum)
Oracle分頁:(利用自帶的rownum)計算引數為開始序號(startNum),結束序號(endNum)【注意:Oracle分頁利用其自帶的rownum,但是rownum在表中不能使用>號(比如select rownum,a。* from A a where rownum > n,查出的都是空),但是可以使用<。這是因為rownum是一個總是從1開始的偽列,Oracle認為rownum>n(n>1的自然數)這種條件依舊不成立,所以查不到記錄】
(4)Mybatis是如何將sql執行結果封裝為目標物件並返回的?
第一種是使用resultMap標籤,逐一定義列名和物件屬性名之間的對映關係。
第二種是使用sql列的別名功能,將列別名書寫為物件屬性名,比如T_NAME AS NAME,物件屬性名一般是name,小寫,但是列名不區分大小寫,Mybatis會忽略列名大小寫,智慧找到與之對應物件屬性名,你甚至可以寫成T_NAME AS NaMe,Mybatis一樣可以正常工作。
進一步提問:resultMap和resultType有啥區別?
resultType:當使用resultType做SQL語句返回結果型別處理時,對於SQL語句查詢出的欄位在相應的pojo中必須有和它相同的欄位對應,而resultType中的內容就是pojo在本專案中的位置。
resultMap:當使用resultMap做SQL語句返回結果型別處理時,通常需要先在mapper。xml中定義resultMap進行pojo和相應表字段的對應關係。然後再使用resultMap。
(5)Mybatis xml對映檔案中,除了常見的select、insert、updae、delete標籤之外,還有哪些標籤及其作用?
除了這四個標籤,還有
(6)為什麼說Mybatis是半自動ORM對映工具?它與全自動的區別在哪裡?
hibernate對很多資料庫的操作已經進行了封裝,hibernate操作物件時,比如往資料庫新增一條記錄,直接save就可以了。(Hibernate屬於全自動ORM對映工具,使用Hibernate查詢關聯物件或者關聯集合物件時,可以根據物件關係模型直接獲取),而Mybatis在查詢關聯物件或關聯集合物件時,需要手動編寫sql來完成,雖然現在已經有不少程式可以自動生成xml檔案,但還是需要自己調整sql,所以稱之為半自動ORM對映工具。這也從側面可以看出hibernate的拓展性不如Mybatis(hibernate做了很多封裝)。
(7)mybatis 為什麼大於不用轉義,小於必須轉義?
mybatis不支援“<”,本質是xml不支援這個符號,<會引起xml格式的錯誤,xml檔案中的標籤是 <…> 這種形式的, 所以當出現 “<” 號時, 會認為是一個標籤的開始。
上一篇:富含益生菌的食物有哪些?
下一篇:大唐的重構(六) 郭子儀單騎退敵