欧美free性护士vide0shd,老熟女,一区二区三区,久久久久夜夜夜精品国产,久久久久久综合网天天,欧美成人护士h版

首頁綜合 正文
目錄

柚子快報邀請碼778899分享:【開發(fā)框架和中間件】

柚子快報邀請碼778899分享:【開發(fā)框架和中間件】

http://yzkb.51969.com/

開發(fā)框架相關(guān)

# 10.1 Spring

# 什么是Spring框架?

Spring是一種輕量級框架,旨在提高開發(fā)人員的開發(fā)效率以及系統(tǒng)的可維護性。

我們一般說的Spring框架就是Spring Framework,它是很多模塊的集合,使用這些模塊可以很方便地協(xié)助我們進行開發(fā)。這些模塊是核心容器、數(shù)據(jù)訪問/集成、Web、AOP(面向切面編程)、工具、消息和測試模塊。比如Core Container中的Core組件是Spring所有組件的核心,Beans組件和Context組件是實現(xiàn)IOC和DI的基礎(chǔ),AOP組件用來實現(xiàn)面向切面編程。

Spring官網(wǎng)列出的Spring的6個特征:

核心技術(shù):依賴注入(DI),AOP,事件(Events),資源,i18n,驗證,數(shù)據(jù)綁定,類型轉(zhuǎn)換,SpEL。測試:模擬對象,TestContext框架,Spring MVC測試,WebTestClient。數(shù)據(jù)訪問:事務(wù),DAO支持,JDBC,ORM,編組XML。Web支持:Spring MVC和Spring WebFlux Web框架。集成:遠程處理,JMS,JCA,JMX,電子郵件,任務(wù),調(diào)度,緩存。語言:Kotlin,Groovy,動態(tài)語言。

# 列舉一些重要的Spring模塊?

下圖對應的是Spring 4.x的版本,目前最新的5.x版本中Web模塊的Portlet組件已經(jīng)被廢棄掉,同時增加了用于異步響應式處理的WebFlux組件。

Spring Core:基礎(chǔ),可以說Spring其他所有的功能都依賴于該類庫。主要提供IOC和DI功能。Spring Aspects:該模塊為與AspectJ的集成提供支持。Spring AOP:提供面向切面的編程實現(xiàn)。Spring JDBC:Java數(shù)據(jù)庫連接。Spring JMS:Java消息服務(wù)。Spring ORM:用于支持Hibernate等ORM工具。Spring Web:為創(chuàng)建Web應用程序提供支持。Spring Test:提供了對JUnit和TestNG測試的支持。

# 什么是IOC? 如何實現(xiàn)的?

IOC(Inversion Of Controll,控制反轉(zhuǎn))是一種設(shè)計思想,就是將原本在程序中手動創(chuàng)建對象的控制權(quán),交給IOC容器來管理,并由IOC容器完成對象的注入。這樣可以很大程度上簡化應用的開發(fā),把應用從復雜的依賴關(guān)系中解放出來。IOC容器就像是一個工廠一樣,當我們需要創(chuàng)建一個對象的時候,只需要配置好配置文件/注解即可,完全不用考慮對象是如何被創(chuàng)建出來的。

Spring 中的 IoC 的實現(xiàn)原理就是工廠模式加反射機制。

示例:

interface Fruit {

public abstract void eat();

}

class Apple implements Fruit {

public void eat(){

System.out.println("Apple");

}

}

class Orange implements Fruit {

public void eat(){

System.out.println("Orange");

}

}

class Factory {

public static Fruit getInstance(String ClassName) {

Fruit f=null;

try {

f=(Fruit)Class.forName(ClassName).newInstance();

} catch (Exception e) {

e.printStackTrace();

}

return f;

}

}

class Client {

public static void main(String[] a) {

Fruit f=Factory.getInstance("io.github.dunwu.spring.Apple");

if(f!=null){

f.eat();

}

}

}

# 什么是AOP? 有哪些AOP的概念?

AOP(Aspect-Oriented Programming,面向切面編程)能夠?qū)⒛切┡c業(yè)務(wù)無關(guān),卻為業(yè)務(wù)模塊所共同調(diào)用的邏輯或責任(例如事務(wù)處理、日志管理、權(quán)限控制等)封裝起來,便于減少系統(tǒng)的重復代碼,降低模塊間的耦合度,并有利于未來的可擴展性和可維護性。

Spring AOP是基于動態(tài)代理的,如果要代理的對象實現(xiàn)了某個接口,那么Spring AOP就會使用JDK動態(tài)代理去創(chuàng)建代理對象;而對于沒有實現(xiàn)接口的對象,就無法使用JDK動態(tài)代理,轉(zhuǎn)而使用CGlib動態(tài)代理生成一個被代理對象的子類來作為代理。

當然也可以使用AspectJ,Spring AOP中已經(jīng)集成了AspectJ,AspectJ應該算得上是Java生態(tài)系統(tǒng)中最完整的AOP框架了。使用AOP之后我們可以把一些通用功能抽象出來,在需要用到的地方直接使用即可,這樣可以大大簡化代碼量。我們需要增加新功能也方便,提高了系統(tǒng)的擴展性。日志功能、事務(wù)管理和權(quán)限管理等場景都用到了AOP。

AOP包含的幾個概念

Jointpoint(連接點):具體的切面點點抽象概念,可以是在字段、方法上,Spring中具體表現(xiàn)形式是PointCut(切入點),僅作用在方法上。Advice(通知): 在連接點進行的具體操作,如何進行增強處理的,分為前置、后置、異常、最終、環(huán)繞五種情況。目標對象:被AOP框架進行增強處理的對象,也被稱為被增強的對象。AOP代理:AOP框架創(chuàng)建的對象,簡單的說,代理就是對目標對象的加強。Spring中的AOP代理可以是JDK動態(tài)代理,也可以是CGLIB代理。Weaving(織入):將增強處理添加到目標對象中,創(chuàng)建一個被增強的對象的過程

總結(jié)為一句話就是:在目標對象(target object)的某些方法(jointpoint)添加不同種類的操作(通知、增強操處理),最后通過某些方法(weaving、織入操作)實現(xiàn)一個新的代理目標對象。

# AOP 有哪些應用場景?

舉幾個例子:

記錄日志(調(diào)用方法后記錄日志)監(jiān)控性能(統(tǒng)計方法運行時間)權(quán)限控制(調(diào)用方法前校驗是否有權(quán)限)事務(wù)管理(調(diào)用方法前開啟事務(wù),調(diào)用方法后提交關(guān)閉事務(wù) )緩存優(yōu)化(第一次調(diào)用查詢數(shù)據(jù)庫,將查詢結(jié)果放入內(nèi)存對象, 第二次調(diào)用,直接從內(nèi)存對象返回,不需要查詢數(shù)據(jù)庫 )

# 有哪些AOP Advice通知的類型?

特定 JoinPoint 處的 Aspect 所采取的動作稱為 Advice。Spring AOP 使用一個 Advice 作為攔截器,在 JoinPoint “周圍”維護一系列的攔截器。

前置通知(Before advice) : 這些類型的 Advice 在 joinpoint 方法之前執(zhí)行,并使用 @Before 注解標記進行配置。后置通知(After advice) :這些類型的 Advice 在連接點方法之后執(zhí)行,無論方法退出是正常還是異常返回,并使用 @After 注解標記進行配置。返回后通知(After return advice) :這些類型的 Advice 在連接點方法正常執(zhí)行后執(zhí)行,并使用@AfterReturning 注解標記進行配置。環(huán)繞通知(Around advice) :這些類型的 Advice 在連接點之前和之后執(zhí)行,并使用 @Around 注解標記進行配置。拋出異常后通知(After throwing advice) :僅在 joinpoint 方法通過拋出異常退出并使用 @AfterThrowing 注解標記配置時執(zhí)行。

# AOP 有哪些實現(xiàn)方式?

實現(xiàn) AOP 的技術(shù),主要分為兩大類:

靜態(tài)代理 - 指使用 AOP 框架提供的命令進行編譯,從而在編譯階段就可生成 AOP 代理類,因此也稱為編譯時增強;

編譯時編織(特殊編譯器實現(xiàn))類加載時編織(特殊的類加載器實現(xiàn))。動態(tài)代理 - 在運行時在內(nèi)存中“臨時”生成 AOP 動態(tài)代理類,因此也被稱為運行時增強。

JDK 動態(tài)代理

JDK Proxy 是 Java 語言自帶的功能,無需通過加載第三方類實現(xiàn);Java 對 JDK Proxy 提供了穩(wěn)定的支持,并且會持續(xù)的升級和更新,Java 8 版本中的 JDK Proxy 性能相比于之前版本提升了很多;JDK Proxy 是通過攔截器加反射的方式實現(xiàn)的;JDK Proxy 只能代理實現(xiàn)接口的類;JDK Proxy 實現(xiàn)和調(diào)用起來比較簡單;CGLIB

CGLib 是第三方提供的工具,基于 ASM 實現(xiàn)的,性能比較高;CGLib 無需通過接口來實現(xiàn),它是針對類實現(xiàn)代理,主要是對指定的類生成一個子類,它是通過實現(xiàn)子類的方式來完成調(diào)用的。

# 談?wù)勀銓GLib的理解?

JDK 動態(tài)代理機制只能代理實現(xiàn)接口的類,一般沒有實現(xiàn)接口的類不能進行代理。使用 CGLib 實現(xiàn)動態(tài)代理,完全不受代理類必須實現(xiàn)接口的限制。

CGLib 的原理是對指定目標類生成一個子類,并覆蓋其中方法實現(xiàn)增強,但因為采用的是繼承,所以不能對 final 修飾的類進行代理。

舉例:

public class CGLibDemo {

// 需要動態(tài)代理的實際對象

static class Sister {

public void sing() {

System.out.println("I am Jinsha, a little sister.");

}

}

static class CGLibProxy implements MethodInterceptor {

private Object target;

public Object getInstance(Object target){

this.target = target;

Enhancer enhancer = new Enhancer();

// 設(shè)置父類為實例類

enhancer.setSuperclass(this.target.getClass());

// 回調(diào)方法

enhancer.setCallback(this);

// 創(chuàng)建代理對象

return enhancer.create();

}

@Override

public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {

System.out.println("introduce yourself...");

Object result = methodProxy.invokeSuper(o,objects);

System.out.println("score...");

return result;

}

}

public static void main(String[] args) {

CGLibProxy cgLibProxy = new CGLibProxy();

//獲取動態(tài)代理類實例

Sister proxySister = (Sister) cgLibProxy.getInstance(new Sister());

System.out.println("CGLib Dynamic object name: " + proxySister.getClass().getName());

proxySister.sing();

}

}

CGLib 的調(diào)用流程就是通過調(diào)用攔截器的 intercept 方法來實現(xiàn)對被代理類的調(diào)用。而攔截邏輯可以寫在 intercept 方法的 invokeSuper(o, objects);的前后實現(xiàn)攔截。

# Spring AOP和AspectJ AOP有什么區(qū)別?

Spring AOP是屬于運行時增強,而AspectJ是編譯時增強。Spring AOP基于代理(Proxying),而AspectJ基于字節(jié)碼操作(Bytecode Manipulation)。

Spring AOP已經(jīng)集成了AspectJ,AspectJ應該算得上是Java生態(tài)系統(tǒng)中最完整的AOP框架了。AspectJ相比于Spring AOP功能更加強大,但是Spring AOP相對來說更簡單。

如果我們的切面比較少,那么兩者性能差異不大。但是,當切面太多的話,最好選擇AspectJ,它比SpringAOP快很多。

# Spring中的bean的作用域有哪些?

singleton:唯一bean實例,Spring中的bean默認都是單例的。 prototype:每次請求都會創(chuàng)建一個新的bean實例。 request:每一次HTTP請求都會產(chǎn)生一個新的bean,該bean僅在當前HTTP request內(nèi)有效。 session:每一次HTTP請求都會產(chǎn)生一個新的bean,該bean僅在當前HTTP session內(nèi)有效。 global-session:全局session作用域,僅僅在基于Portlet的Web應用中才有意義,Spring5中已經(jīng)沒有了。Portlet是能夠生成語義代碼(例如HTML)片段的小型Java Web插件。它們基于Portlet容器,可以像Servlet一樣處理HTTP請求。但是與Servlet不同,每個Portlet都有不同的會話。

# Spring中的單例bean的線程安全問題了解嗎?

大部分時候我們并沒有在系統(tǒng)中使用多線程,所以很少有人會關(guān)注這個問題。單例bean存在線程問題,主要是因為當多個線程操作同一個對象的時候,對這個對象的非靜態(tài)成員變量的寫操作會存在線程安全問題。

有兩種常見的解決方案:

1.在bean對象中盡量避免定義可變的成員變量(不太現(xiàn)實)。

2.在類中定義一個ThreadLocal成員變量,將需要的可變成員變量保存在ThreadLocal中(推薦的一種方式)。

# Spring中的bean生命周期?

Bean的完整生命周期經(jīng)歷了各種方法調(diào)用,這些方法可以劃分為以下幾類:

Bean自身的方法: 這個包括了Bean本身調(diào)用的方法和通過配置文件中的init-method和destroy-method指定的方法Bean級生命周期接口方法: 這個包括了BeanNameAware、BeanFactoryAware、ApplicationContextAware;當然也包括InitializingBean和DiposableBean這些接口的方法(可以被@PostConstruct和@PreDestroy注解替代)容器級生命周期接口方法: 這個包括了InstantiationAwareBeanPostProcessor 和 BeanPostProcessor 這兩個接口實現(xiàn),一般稱它們的實現(xiàn)類為“后處理器”。工廠后處理器接口方法: 這個包括了AspectJWeavingEnabler, ConfigurationClassPostProcessor, CustomAutowireConfigurer等等非常有用的工廠后處理器接口的方法。工廠后處理器也是容器級的。在應用上下文裝配配置文件之后立即調(diào)用。

具體而言,流程如下

如果 BeanFactoryPostProcessor 和 Bean 關(guān)聯(lián), 則調(diào)用postProcessBeanFactory方法.(即首先嘗試從Bean工廠中獲取Bean)如果 InstantiationAwareBeanPostProcessor 和 Bean 關(guān)聯(lián),則調(diào)用postProcessBeforeInstantiation方法根據(jù)配置情況調(diào)用 Bean 構(gòu)造方法實例化 Bean。利用依賴注入完成 Bean 中所有屬性值的配置注入。如果 InstantiationAwareBeanPostProcessor 和 Bean 關(guān)聯(lián),則調(diào)用postProcessAfterInstantiation方法和postProcessProperties調(diào)用xxxAware接口 (上圖只是給了幾個例子)

第一類Aware接口

如果 Bean 實現(xiàn)了 BeanNameAware 接口,則 Spring 調(diào)用 Bean 的 setBeanName() 方法傳入當前 Bean 的 id 值。如果 Bean 實現(xiàn)了 BeanClassLoaderAware 接口,則 Spring 調(diào)用 setBeanClassLoader() 方法傳入classLoader的引用。如果 Bean 實現(xiàn)了 BeanFactoryAware 接口,則 Spring 調(diào)用 setBeanFactory() 方法傳入當前工廠實例的引用。第二類Aware接口

如果 Bean 實現(xiàn)了 EnvironmentAware 接口,則 Spring 調(diào)用 setEnvironment() 方法傳入當前 Environment 實例的引用。如果 Bean 實現(xiàn)了 EmbeddedValueResolverAware 接口,則 Spring 調(diào)用 setEmbeddedValueResolver() 方法傳入當前 StringValueResolver 實例的引用。如果 Bean 實現(xiàn)了 ApplicationContextAware 接口,則 Spring 調(diào)用 setApplicationContext() 方法傳入當前 ApplicationContext 實例的引用。...如果 BeanPostProcessor 和 Bean 關(guān)聯(lián),則 Spring 將調(diào)用該接口的預初始化方法 postProcessBeforeInitialzation() 對 Bean 進行加工操作,此處非常重要,Spring 的 AOP 就是利用它實現(xiàn)的。如果 Bean 實現(xiàn)了 InitializingBean 接口,則 Spring 將調(diào)用 afterPropertiesSet() 方法。(或者有執(zhí)行@PostConstruct注解的方法)如果在配置文件中通過 init-method 屬性指定了初始化方法,則調(diào)用該初始化方法。如果 BeanPostProcessor 和 Bean 關(guān)聯(lián),則 Spring 將調(diào)用該接口的初始化方法 postProcessAfterInitialization()。此時,Bean 已經(jīng)可以被應用系統(tǒng)使用了。如果在 中指定了該 Bean 的作用范圍為 scope="singleton",則將該 Bean 放入 Spring IoC 的緩存池中,將觸發(fā) Spring 對該 Bean 的生命周期管理;如果在 中指定了該 Bean 的作用范圍為 scope="prototype",則將該 Bean 交給調(diào)用者,調(diào)用者管理該 Bean 的生命周期,Spring 不再管理該 Bean。如果 Bean 實現(xiàn)了 DisposableBean 接口,則 Spring 會調(diào)用 destory() 方法將 Spring 中的 Bean 銷毀;(或者有執(zhí)行@PreDestroy注解的方法)如果在配置文件中通過 destory-method 屬性指定了 Bean 的銷毀方法,則 Spring 將調(diào)用該方法對 Bean 進行銷毀。

# 說說自己對于Spring MVC的了解?

MVC是一種設(shè)計模式,Spring MVC是一款很優(yōu)秀的MVC框架。Spring MVC可以幫助我們進行更簡潔的Web層的開發(fā),并且它天生與Spring框架集成。Spring MVC下我們一般把后端項目分為Service層(處理業(yè)務(wù))、Dao層(數(shù)據(jù)庫操作)、Entity層(實體類)、Controller層(控制層,返回數(shù)據(jù)給前臺頁面)。

# Spring MVC的工作原理了解嘛?

流程說明:

1.客戶端(瀏覽器)發(fā)送請求,直接請求到DispatcherServlet。

2.DispatcherServlet根據(jù)請求信息調(diào)用HandlerMapping,解析請求對應的Handler。

3.解析到對應的Handler(也就是我們平常說的Controller控制器)。

4.HandlerAdapter會根據(jù)Handler來調(diào)用真正的處理器來處理請求和執(zhí)行相對應的業(yè)務(wù)邏輯。

5.處理器處理完業(yè)務(wù)后,會返回一個ModelAndView對象,Model是返回的數(shù)據(jù)對象,View是邏輯上的View。

6.ViewResolver會根據(jù)邏輯View去查找實際的View。

7.DispatcherServlet把返回的Model傳給View(視圖渲染)。

8.把View返回給請求者(瀏覽器)。

# Spring框架中用到了哪些設(shè)計模式?

舉幾個例子

1.工廠設(shè)計模式:Spring使用工廠模式通過BeanFactory和ApplicationContext創(chuàng)建bean對象。

2.代理設(shè)計模式:Spring AOP功能的實現(xiàn)。

3.單例設(shè)計模式:Spring中的bean默認都是單例的。

4.模板方法模式:Spring中的jdbcTemplate、hibernateTemplate等以Template結(jié)尾的對數(shù)據(jù)庫操作的類,它們就使用到了模板模式。

5.包裝器設(shè)計模式:我們的項目需要連接多個數(shù)據(jù)庫,而且不同的客戶在每次訪問中根據(jù)需要會去訪問不同的數(shù)據(jù)庫。這種模式讓我們可以根據(jù)客戶的需求能夠動態(tài)切換不同的數(shù)據(jù)源。

6.觀察者模式:Spring事件驅(qū)動模型就是觀察者模式很經(jīng)典的一個應用。

7.適配器模式:Spring AOP的增強或通知(Advice)使用到了適配器模式、Spring MVC中也是用到了適配器模式適配Controller。

# @Component和@Bean的區(qū)別是什么?

1.作用對象不同。@Component注解作用于類,而@Bean注解作用于方法。

2.@Component注解通常是通過類路徑掃描來自動偵測以及自動裝配到Spring容器中(我們可以使用@ComponentScan注解定義要掃描的路徑)。@Bean注解通常是在標有該注解的方法中定義產(chǎn)生這個bean,告訴Spring這是某個類的實例,當我需要用它的時候還給我。

3.@Bean注解比@Component注解的自定義性更強,而且很多地方只能通過@Bean注解來注冊bean。比如當引用第三方庫的類需要裝配到Spring容器的時候,就只能通過@Bean注解來實現(xiàn)。

@Bean注解的使用示例:

@Configuration

public class AppConfig {

@Bean

public TransferService transferService() {

return new TransferServiceImpl();

}

}

上面的代碼相當于下面的XML配置:

下面這個例子是無法通過@Component注解實現(xiàn)的:

@Bean

public OneService getService(status) {

case (status) {

when 1:

return new serviceImpl1();

when 2:

return new serviceImpl2();

when 3:

return new serviceImpl3();

}

}

# 將一個類聲明為Spring的bean的注解有哪些?

我們一般使用@Autowired注解去自動裝配bean。而想要把一個類標識為可以用@Autowired注解自動裝配的bean,可以采用以下的注解實現(xiàn):

1.@Component注解。通用的注解,可標注任意類為Spring組件。如果一個Bean不知道屬于哪一個層,可以使用@Component注解標注。

2.@Repository注解。對應持久層,即Dao層,主要用于數(shù)據(jù)庫相關(guān)操作。

3.@Service注解。對應服務(wù)層,即Service層,主要涉及一些復雜的邏輯,需要用到Dao層(注入)。

4.@Controller注解。對應Spring MVC的控制層,即Controller層,主要用于接受用戶請求并調(diào)用Service層的方法返回數(shù)據(jù)給前端頁面。

# Spring事務(wù)管理的方式有幾種?

1.編程式事務(wù):在代碼中硬編碼(不推薦使用)。

2.聲明式事務(wù):在配置文件中配置(推薦使用),分為基于XML的聲明式事務(wù)和基于注解的聲明式事務(wù)。

# Spring事務(wù)中的隔離級別有哪幾種?

在TransactionDefinition接口中定義了五個表示隔離級別的常量:

ISOLATION_DEFAULT:使用后端數(shù)據(jù)庫默認的隔離級別,Mysql默認采用的REPEATABLE_READ隔離級別;Oracle默認采用的READ_COMMITTED隔離級別。

ISOLATION_READ_UNCOMMITTED:最低的隔離級別,允許讀取尚未提交的數(shù)據(jù)變更,可能會導致臟讀、幻讀或不可重復讀。

ISOLATION_READ_COMMITTED:允許讀取并發(fā)事務(wù)已經(jīng)提交的數(shù)據(jù),可以阻止臟讀,但是幻讀或不可重復讀仍有可能發(fā)生

ISOLATION_REPEATABLE_READ:對同一字段的多次讀取結(jié)果都是一致的,除非數(shù)據(jù)是被本身事務(wù)自己所修改,可以阻止臟讀和不可重復讀,但幻讀仍有可能發(fā)生。

ISOLATION_SERIALIZABLE:最高的隔離級別,完全服從ACID的隔離級別。所有的事務(wù)依次逐個執(zhí)行,這樣事務(wù)之間就完全不可能產(chǎn)生干擾,也就是說,該級別可以防止臟讀、不可重復讀以及幻讀。但是這將嚴重影響程序的性能。通常情況下也不會用到該級別。

# Spring事務(wù)中有哪幾種事務(wù)傳播行為?

在TransactionDefinition接口中定義了7個表示事務(wù)傳播行為的常量。

支持當前事務(wù)的情況:

PROPAGATION_REQUIRED:如果當前存在事務(wù),則加入該事務(wù);如果當前沒有事務(wù),則創(chuàng)建一個新的事務(wù)。

PROPAGATION_SUPPORTS: 如果當前存在事務(wù),則加入該事務(wù);如果當前沒有事務(wù),則以非事務(wù)的方式繼續(xù)運行。

PROPAGATION_MANDATORY: 如果當前存在事務(wù),則加入該事務(wù);如果當前沒有事務(wù),則拋出異常。(mandatory:強制性)。

不支持當前事務(wù)的情況:

PROPAGATION_REQUIRES_NEW: 創(chuàng)建一個新的事務(wù),如果當前存在事務(wù),則把當前事務(wù)掛起。

PROPAGATION_NOT_SUPPORTED: 以非事務(wù)方式運行,如果當前存在事務(wù),則把當前事務(wù)掛起。

PROPAGATION_NEVER: 以非事務(wù)方式運行,如果當前存在事務(wù),則拋出異常。

其他情況:

PROPAGATION_NESTED: 如果當前存在事務(wù),則創(chuàng)建一個事務(wù)作為當前事務(wù)的嵌套事務(wù)來運行;如果當前沒有事務(wù),則該取值等價于PROPAGATION_REQUIRED。

# Bean Factory和ApplicationContext有什么區(qū)別?

ApplicationContex提供了一種解析文本消息的方法,一種加載文件資源(如圖像)的通用方法,它們可以將事件發(fā)布到注冊為偵聽器的bean。此外,可以在應用程序上下文中以聲明方式處理容器中的容器或容器上的操作,這些操作必須以編程方式與Bean Factory一起處理。ApplicationContext實現(xiàn)MessageSource,一個用于獲取本地化消息的接口,實際的實現(xiàn)是可插入的。

# 如何定義bean的范圍?

在Spring中定義一個時,我們也可以為bean聲明一個范圍。它可以通過bean定義中的scope屬性定義。例如,當Spring每次需要生成一個新的bean實例時,bean'sscope屬性就是原型。另一方面,當每次需要Spring都必須返回相同的bean實例時,bean scope屬性必須設(shè)置為singleton。

# 可以通過多少種方式完成依賴注入?

通常,依賴注入可以通過三種方式完成,即:

構(gòu)造函數(shù)注入setter 注入接口注入

# 10.2 Spring Boot

# 什么是SpringBoot?

Spring Boot 是 Spring 開源組織下的子項目,是 Spring 組件一站式解決方案,主要是簡化了使用 Spring 的難度,簡省了繁重的配置,提供了各種啟動器,開發(fā)者能快速上手。

用來簡化Spring應用的初始搭建以及開發(fā)過程,使用特定的方式來進行配置創(chuàng)建獨立的Spring引用程序main方法運行嵌入的tomcat無需部署war文件簡化maven配置自動配置Spring添加對應的功能starter自動化配置SpringBoot來簡化Spring應用開發(fā),約定大于配置,去繁化簡

# 為什么使用SpringBoot?

獨立運行

Spring Boot 而且內(nèi)嵌了各種 servlet 容器,Tomcat、Jetty 等,現(xiàn)在不再需要打成war 包部署到容器中,Spring Boot 只要打成一個可執(zhí)行的 jar 包就能獨立運行,所有的依賴包都在一個 jar 包內(nèi)。

簡化配置

spring-boot-starter-web 啟動器自動依賴其他組件,簡少了 maven 的配置。

自動配置

Spring Boot 能根據(jù)當前類路徑下的類、jar 包來自動配置 bean,如添加一個 spring

boot-starter-web 啟動器就能擁有 web 的功能,無需其他配置。

無代碼生成和XML配置

Spring Boot 配置過程中無代碼生成,也無需 XML 配置文件就能完成所有配置工作,這一切都是借助于條件注解完成的,這也是 Spring4.x 的核心功能之一。

應用監(jiān)控

Spring Boot 提供一系列端點可以監(jiān)控服務(wù)及應用,做健康檢測。

# Spring、Spring MVC和SpringBoot有什么區(qū)別?

Spring

Spring最重要的特征是依賴注入。所有Spring Modules不是依賴注入就是IOC控制反轉(zhuǎn)。

當我們恰當?shù)氖褂肈I或者是IOC的時候,可以開發(fā)松耦合應用。

Spring MVC

Spring MVC提供了一種分離式的方法來開發(fā)Web應用。通過運用像DispatcherServelet,ModelAndView 和 ViewResolver 等一些簡單的概念,開發(fā) Web 應用將會變的非常簡單。

SpringBoot

Spring和Spring MVC的問題在于需要配置大量的參數(shù)。

SpringBoot通過一個自動配置和啟動的項來解決這個問題。

# SpringBoot自動配置的原理?

在Spring程序main方法中,添加@SpringBootApplication或者@EnableAutoConfiguration會自動去maven中讀取每個starter中的spring.factories文件,該文件里配置了所有需要被創(chuàng)建的Spring容器中的bean

# Spring Boot的核心注解是哪些?他主由哪幾個注解組成的?

啟動類上面的注解是@SpringBootApplication,他也是SpringBoot的核心注解,主要組合包含了以下3個注解:

@SpringBootConfiguration:組合了@Configuration注解,實現(xiàn)配置文件的功能;@EnableAutoConfiguration:打開自動配置的功能,也可以關(guān)閉某個自動配置的選項,如關(guān)閉數(shù)據(jù)源自動配置的功能:@SpringBootApplication(exclude={DataSourceAutoConfiguration.class});@ComponentScan:Spring組件掃描。

# SpringBoot的核心配置文件有哪幾個?他們的區(qū)別是什么?

SpringBoot的核心配置文件是application和bootstrap配置文件。

application配置文件這個容易理解,主要用于Spring Boot項目的自動化配置。

bootstrap配置文件有以下幾個應用場景:

使用Spring Cloud Config配置中心時,這時需要在bootstrap配置文件中添加連接到配置中心的配置屬性來加載外部配置中心的配置信息;一些固定的不能被覆蓋的屬性;一些加密/解密的場景;

# 什么是Spring Boot Starter?有哪些常用的?

和自動配置一樣,Spring Boot Starter的目的也是簡化配置,而Spring Boot Starter解決的是依賴管理配置復雜的問題,有了它,當我需要構(gòu)建一個Web應用程序時,不必再遍歷所有的依賴包,一個一個地添加到項目的依賴管理中,而是只需要一個配置spring-boot-starter-web, 同理,如果想引入持久化功能,可以配置spring-boot-starter-data-jpa:

org.springframework.boot

spring-boot-starter-web

Spring Boot 也提供了其它的啟動器項目包括,包括用于開發(fā)特定類型應用程序的典型依賴項。

spring-boot-starter-web-services - SOAP Web Services

spring-boot-starter-web - Web 和 RESTful 應用程序

spring-boot-starter-test - 單元測試和集成測試

spring-boot-starter-jdbc - 傳統(tǒng)的 JDBC

spring-boot-starter-hateoas - 為服務(wù)添加 HATEOAS 功能

spring-boot-starter-security - 使用 SpringSecurity 進行身份驗證和授權(quán)

spring-boot-starter-data-jpa - 帶有 Hibernate 的 Spring Data JPA

spring-boot-starter-data-rest - 使用 Spring Data REST 公布簡單的 REST 服務(wù)

# spring-boot-starter-parent有什么作用?

我們知道,新建一個SpringBoot項目,默認都是有parent的,這個parent就是spring-boot-starter-parent,spring-boot-starter-parent主要有如下作用:

定義了Java編譯版本使用UTF-8格式編碼繼承自spring-boor-dependencies,這里面定義了依賴的版本,也正是因為繼承了這個依賴,所以我們在寫依賴時才不需要寫版本號執(zhí)行打包操作的配置自動化的資源過濾自動化的插件配置

# 如何自定義Spring Boot Starter?

實現(xiàn)功能添加Properties

@Data

@ConfigurationProperties(prefix = "com.pdai")

public class DemoProperties {

private String version;

private String name;

}

添加AutoConfiguration

@Configuration

@EnableConfigurationProperties(DemoProperties.class)

public class DemoAutoConfiguration {

@Bean

public com.pdai.demo.module.DemoModule demoModule(DemoProperties properties){

com.pdai.demo.module.DemoModule demoModule = new com.pdai.demo.module.DemoModule();

demoModule.setName(properties.getName());

demoModule.setVersion(properties.getVersion());

return demoModule;

}

}

添加spring.factory

在META-INF下創(chuàng)建spring.factory文件

org.springframework.boot.autoconfigure.EnableAutoConfiguration=\

com.pdai.demospringbootstarter.DemoAutoConfiguration

# 為什么需要spring-boot-maven-plugin?

spring-boot-maven-plugin提供了一些像jar一樣打包或者運行應用程序的命令。

spring-boot:run 運行SpringBoot應用程序;spring-boot:repackage 重新打包你的jar包或者是war包使其可執(zhí)行spring-boot:start和spring-boot:stop管理Spring Boot應用程序的生命周期spring-boot:build-info生成執(zhí)行器可以使用的構(gòu)造信息

# SpringBoot 打成jar和普通的jar有什么區(qū)別?

Spring Boot 項目最終打包成的 jar 是可執(zhí)行 jar ,這種 jar 可以直接通過java -jar xxx.jar命令來運行,這種 jar 不可以作為普通的 jar 被其他項目依賴,即使依賴了也無法使用其中的類。

Spring Boot 的 jar 無法被其他項目依賴,主要還是他和普通 jar 的結(jié)構(gòu)不同。普通的 jar 包,解壓后直接就是包名,包里就是我們的代碼,而 Spring Boot 打包成的可執(zhí)行 jar 解壓后,在 \BOOT-INF\classes目錄下才是我們的代碼,因此無法被直接引用。如果非要引用,可以在 pom.xml 文件中增加配置,將 Spring Boot 項目打包成兩個 jar ,一個可執(zhí)行,一個可引用。

# 如何使用Spring Boot實現(xiàn)異常處理?

Spring提供了一種使用ControllerAdvice處理異常的非常有用的方法。通過實現(xiàn)一個ControlerAdvice類,來處理控制類拋出的所有異常。

# SpringBoot 實現(xiàn)熱部署有哪幾種方式?

主要有兩種方式:

Spring LoadedSpring-boot-devtools

# Spring Boot中的監(jiān)視器是什么?

Spring boot actuator是spring啟動框架中的重要功能之一。Spring boot監(jiān)視器可幫助您訪問生產(chǎn)環(huán)境中正在運行的應用程序的當前狀態(tài)。

有幾個指標必須在生產(chǎn)環(huán)境中進行檢查和監(jiān)控。即使一些外部應用程序可能正在使用這些服務(wù)來向相關(guān)人員觸發(fā)警報消息。監(jiān)視器模塊公開了一組可直接作為HTTP URL訪問的REST端點來檢查狀態(tài)。

# Spring Boot 可以兼容老 Spring 項目嗎?

可以兼容,使用 @ImportResource 注解導入老 Spring 項目配置文件。

# 10.3 Spring Security

# 什么是Spring Security?核心功能?

Spring Security是基于Spring的安全框架.它提供全面的安全性解決方案,同時在Web請求級別和調(diào)用級別確認和授權(quán).在Spring Framework基礎(chǔ)上,Spring Security充分利用了依賴注入(DI)和面向切面編程(AOP)功能,為應用系統(tǒng)提供聲明式的安全訪問控制功能,建曬了為企業(yè)安全控制編寫大量重復代碼的工作,是一個輕量級的安全框架,并且很好集成Spring MVC

spring security 的核心功能主要包括:

認證(Authentication):指的是驗證某個用戶是否為系統(tǒng)中的合法主體,也就是說用戶能否訪問該系統(tǒng)。授權(quán)(Authorization):指的是驗證某個用戶是否有權(quán)限執(zhí)行某個操作攻擊防護:指的是防止偽造身份

# Spring Security的原理?

簡單談?wù)勂渲械囊c

基于Filter技術(shù)實現(xiàn)?

首先SpringSecurity是基于Filter技術(shù)實現(xiàn)的。Spring通過DelegatingFilterProxy建立Web容器和Spring ApplicationContext的聯(lián)系,而SpringSecurity使用FilterChainProxy 注冊SecurityFilterChain。

認證模塊的實現(xiàn)?

SecurityContextHolder(用于存儲授權(quán)信息)

手動授權(quán)的例子(SecurityContextHolder.getContext().setAuthentication(authentication)這種授權(quán)方式多線程不安全):

SecurityContext context = SecurityContextHolder.createEmptyContext();

Authentication authentication =

new TestingAuthenticationToken("username", "password", "ROLE_USER");

context.setAuthentication(authentication);

SecurityContextHolder.setContext(context);

除了手動授權(quán)外,SpringSecurity通過AuthenticationManager和ProviderManager進行授權(quán)。其中AuthenticationProvider代表不同的認證機制(最常用的賬號/密碼)。

授權(quán)模塊的實現(xiàn)?

認證完成之后,SpringSecurity通過AccessDecisionManager 完成授權(quán)操作。除了全局的授權(quán)配置之外,也可以通過@PreAuthorize, @PreFilter, @PostAuthorize , @PostFilter注解實現(xiàn)方法級別的權(quán)限控制。

# Spring Security基于用戶名和密碼的認證模式流程?

請求的用戶名密碼可以通過表單登錄,基礎(chǔ)認證,數(shù)字認證三種方式從HttpServletRequest中獲得,用于認證的數(shù)據(jù)源策略有內(nèi)存,數(shù)據(jù)庫,ldap,自定義等。

攔截未授權(quán)的請求,重定向到登錄頁面

表單登錄的過程,進行賬號密碼認證

# 10.4 MyBatis

# 10.5 JPA

# 10.6 日志框架

# 什么是日志系統(tǒng)和日志門面?分別有哪些框架?

日志系統(tǒng)是具體的日志框架,日志門面是不提供日志的具體實現(xiàn),而是在運行時動態(tài)的綁定日志實現(xiàn)組件來工作,是一種外觀模式。

日志系統(tǒng)

java.util.logging (JUL),JDK1.4 開始,通過 java.util.logging 提供日志功能。雖然是官方自帶的log lib,JUL的使用確不廣泛。Log4j,Log4j 是 apache 的一個開源項目,創(chuàng)始人 Ceki Gulcu。Log4j 應該說是 Java 領(lǐng)域資格最老,應用最廣的日志工具。Log4j 是高度可配置的,并可通過在運行時的外部文件配置。它根據(jù)記錄的優(yōu)先級別,并提供機制,以指示記錄信息到許多的目的地,諸如:數(shù)據(jù)庫,文件,控制臺,UNIX 系統(tǒng)日志等。Log4j 的短板在于性能,在Logback 和 Log4j2 出來之后,Log4j的使用也減少了。Logback,Logback 是由 log4j 創(chuàng)始人 Ceki Gulcu 設(shè)計的又一個開源日志組件,是作為 Log4j 的繼承者來開發(fā)的,提供了性能更好的實現(xiàn),異步 logger,F(xiàn)ilter等更多的特性。Log4j2,維護 Log4j 的人為了性能又搞出了 Log4j2。Log4j2 和 Log4j1.x 并不兼容,設(shè)計上很大程度上模仿了 SLF4J/Logback,性能上也獲得了很大的提升。Log4j2 也做了 Facade/Implementation 分離的設(shè)計,分成了 log4j-api 和 log4j-core。 日志門面

common-logging,common-logging 是 apache 的一個開源項目。也稱Jakarta Commons Logging,縮寫 JCL。slf4j, 全稱為 Simple Logging Facade for Java,即 java 簡單日志門面。作者又是 Ceki Gulcu!這位大神寫了 Log4j、Logback 和 slf4j。類似于 Common-Logging,slf4j 是對不同日志框架提供的一個 API 封裝,可以在部署的時候不修改任何配置即可接入一種日志實現(xiàn)方案。但是,slf4j 在編譯時靜態(tài)綁定真正的 Log 庫。使用 SLF4J 時,如果你需要使用某一種日志實現(xiàn),那么你必須選擇正確的 SLF4J 的 jar 包的集合(各種橋接包)。

# 日志庫中使用橋接模式解決什么問題?

什么是橋接呢?

假如你正在開發(fā)應用程序所調(diào)用的組件當中已經(jīng)使用了 common-logging,這時你需要 jcl-over-slf4j.jar 把日志信息輸出重定向到 slf4j-api,slf4j-api 再去調(diào)用 slf4j 實際依賴的日志組件。這個過程稱為橋接。

從圖中應該可以看出,無論你的老項目中使用的是 common-logging 或是直接使用 log4j、java.util.logging,都可以使用對應的橋接 jar 包來解決兼容問題。

slf4j 兼容 common-logging

org.slf4j

jcl-over-slf4j

1.7.12

slf4j 兼容 log4j

org.slf4j

log4j-over-slf4j

1.7.12

# 在日志配置時會考慮哪些點?

支持日志路徑,日志level等配置日志控制配置通過application.yml下發(fā)按天生成日志,當天的日志>50MB回滾最多保存10天日志生成的日志中Pattern自定義Pattern中添加用戶自定義的MDC字段,比如用戶信息(當前日志是由哪個用戶的請求產(chǎn)生),request信息。此種方式可以通過AOP切面控制,在MDC中添加requestID,在spring-logback.xml中配置Pattern。根據(jù)不同的運行環(huán)境設(shè)置Profile - dev,test,product對控制臺,Err和全量日志分別配置對第三方包路徑日志控制

# 對Java日志組件選型的建議?

slf4j已經(jīng)成為了Java日志組件的明星選手,可以完美替代JCL,使用JCL橋接庫也能完美兼容一切使用JCL作為日志門面的類庫,現(xiàn)在的新系統(tǒng)已經(jīng)沒有不使用slf4j作為日志API的理由了。

日志記錄服務(wù)方面,log4j在功能上輸于logback和log4j2,在性能方面log4j2則全面超越log4j和logback。所以新系統(tǒng)應該在logback和log4j2中做出選擇,對于性能有很高要求的系統(tǒng),應優(yōu)先考慮log4j2。

# 對日志架構(gòu)使用比較好的實踐?

說幾個點:

總是使用Log Facade,而不是具體Log Implementation只添加一個 Log Implementation依賴具體的日志實現(xiàn)依賴應該設(shè)置為optional和使用runtime scope如果有必要, 排除依賴的第三方庫中的Log Impementation依賴避免為不會輸出的log付出代價日志格式中最好不要使用行號,函數(shù)名等字段

# 對現(xiàn)有系統(tǒng)日志架構(gòu)的改造建議?

如果現(xiàn)有系統(tǒng)使用JCL作為日志門面,又確實面臨著JCL的ClassLoader機制帶來的問題,完全可以引入slf4j并通過橋接庫將JCL api輸出的日志橋接至slf4j,再通過適配庫適配至現(xiàn)有的日志輸出服務(wù)(如log4j)。

這樣做不需要任何代碼級的改造,就可以解決JCL的ClassLoader帶來的問題,但沒有辦法享受日志模板等slf4j的api帶來的優(yōu)點。不過之后在現(xiàn)系統(tǒng)上開發(fā)的新功能就可以使用slf4j的api了,老代碼也可以分批進行改造。

如果現(xiàn)有系統(tǒng)使用JCL作為日志門面,又頭疼JCL不支持logback和log4j2等新的日志服務(wù),也可以通過橋接庫以slf4j替代JCL,但同樣無法直接享受slf4j api的優(yōu)點。

如果想要使用slf4j的api,那么就不得不進行代碼改造了,當然改造也可以參考1中提到的方式逐步進行。

如果現(xiàn)系統(tǒng)面臨著log4j的性能問題,可以使用Apache Logging提供的log4j到log4j2的橋接庫log4j-1.2-api,把通過log4j api輸出的日志橋接至log4j2。這樣可以最快地使用上log4j2的先進性能,但組件中缺失了slf4j,對后續(xù)進行日志架構(gòu)改造的靈活性有影響。另一種辦法是先把log4j橋接至slf4j,再使用slf4j到log4j2的適配庫。這樣做稍微麻煩了一點,但可以逐步將系統(tǒng)中的日志輸出標準化為使用slf4j的api,為后面的工作打好基礎(chǔ)。

# 10.7 Tomcat

# Tomcat 整體架構(gòu)的設(shè)計?

Server: 表示服務(wù)器,它提供了一種優(yōu)雅的方式來啟動和停止整個系統(tǒng),不必單獨啟停連接器和容器;它是Tomcat構(gòu)成的頂級構(gòu)成元素,所有一切均包含在Server中; Service: 表示服務(wù),Server可以運行多個服務(wù)。比如一個Tomcat里面可運行訂單服務(wù)、支付服務(wù)、用戶服務(wù)等等;Server的實現(xiàn)類StandardServer可以包含一個到多個Services, Service的實現(xiàn)類為StandardService調(diào)用了容器(Container)接口,其實是調(diào)用了Servlet Engine(引擎),而且StandardService類中也指明了該Service歸屬的Server; Container: 表示容器,可以看做Servlet容器;引擎(Engine)、主機(Host)、上下文(Context)和Wraper均繼承自Container接口,所以它們都是容器。

Engine -- 引擎Host -- 主機Context -- 上下文Wrapper -- 包裝器 Connector: 表示連接器, 它將Service和Container連接起來,首先它需要注冊到一個Service,它的作用就是把來自客戶端的請求轉(zhuǎn)發(fā)到Container(容器),這就是它為什么稱作連接器, 它支持的協(xié)議如下:

支持AJP協(xié)議支持Http協(xié)議支持Https協(xié)議 Service內(nèi)部還有各種支撐組件,下面簡單羅列一下這些組件

Manager -- 管理器,用于管理會話SessionLogger -- 日志器,用于管理日志Loader -- 加載器,和類加載有關(guān),只會開放給Context所使用Pipeline -- 管道組件,配合Valve實現(xiàn)過濾器功能Valve -- 閥門組件,配合Pipeline實現(xiàn)過濾器功能Realm -- 認證授權(quán)組件

# Tomcat 一個請求的處理流程?

假設(shè)來自客戶的請求為:http://localhost:8080/test/index.jsp 請求被發(fā)送到本機端口8080,被在那里偵聽的Coyote HTTP/1.1 Connector,然后

Connector把該請求交給它所在的Service的Engine來處理,并等待Engine的回應Engine獲得請求localhost:8080/test/index.jsp,匹配它所有虛擬主機HostEngine匹配到名為localhost的Host(即使匹配不到也把請求交給該Host處理,因為該Host被定義為該Engine的默認主機)localhost Host獲得請求/test/index.jsp,匹配它所擁有的所有ContextHost匹配到路徑為/test的Context(如果匹配不到就把該請求交給路徑名為""的Context去處理)path="/test"的Context獲得請求/index.jsp,在它的mapping table中尋找對應的servletContext匹配到URL PATTERN為*.jsp的servlet,對應于JspServlet類,構(gòu)造HttpServletRequest對象和HttpServletResponse對象,作為參數(shù)調(diào)用JspServlet的doGet或doPost方法Context把執(zhí)行完了之后的HttpServletResponse對象返回給HostHost把HttpServletResponse對象返回給EngineEngine把HttpServletResponse對象返回給ConnectorConnector把HttpServletResponse對象返回給客戶browser

# Tomcat 中類加載機制?

在Bootstrap中我們可以看到有如下三個classloader

ClassLoader commonLoader = null;

ClassLoader catalinaLoader = null;

ClassLoader sharedLoader = null;

為什么要設(shè)計多個類加載器?

如果所有的類都使用一個類加載器來加載,會出現(xiàn)什么問題呢?

假如我們自己編寫一個類java.util.Object,它的實現(xiàn)可能有一定的危險性或者隱藏的bug。而我們知道Java自帶的核心類里面也有java.util.Object,如果JVM啟動的時候先行加載的是我們自己編寫的java.util.Object,那么就有可能出現(xiàn)安全問題!

所以,Sun(后被Oracle收購)采用了另外一種方式來保證最基本的、也是最核心的功能不會被破壞。你猜的沒錯,那就是雙親委派模式!

什么是雙親委派模型?

雙親委派模型解決了類錯亂加載的問題,也設(shè)計得非常精妙。

雙親委派模式對類加載器定義了層級,每個類加載器都有一個父類加載器。在一個類需要加載的時候,首先委派給父類加載器來加載,而父類加載器又委派給祖父類加載器來加載,以此類推。如果父類及上面的類加載器都加載不了,那么由當前類加載器來加載,并將被加載的類緩存起來。

所以上述類是這么加載的

Java自帶的核心類 -- 由啟動類加載器加載 Java支持的可擴展類 -- 由擴展類加載器加載 我們自己編寫的類 -- 默認由應用程序類加載器或其子類加載 為什么Tomcat的類加載器也不是雙親委派模型?

Java默認的類加載機制是通過雙親委派模型來實現(xiàn)的,而Tomcat實現(xiàn)的方式又和雙親委派模型有所區(qū)別。

原因在于一個Tomcat容器允許同時運行多個Web程序,每個Web程序依賴的類又必須是相互隔離的。因此,如果Tomcat使用雙親委派模式來加載類的話,將導致Web程序依賴的類變?yōu)楣蚕淼摹?/p>

舉個例子,假如我們有兩個Web程序,一個依賴A庫的1.0版本,另一個依賴A庫的2.0版本,他們都使用了類xxx.xx.Clazz,其實現(xiàn)的邏輯因類庫版本的不同而結(jié)構(gòu)完全不同。那么這兩個Web程序的其中一個必然因為加載的Clazz不是所使用的Clazz而出現(xiàn)問題!而這對于開發(fā)來說是非常致命的!

# Tomcat Container設(shè)計?

我們看下幾個Container之間的關(guān)系:

從上圖上,我們也可以看出Container頂層也是基于Lifecycle的組件設(shè)計的。

在設(shè)計Container組件層次組件時,上述4個組件分別做什么的呢?為什么要四種組件呢?

Engine - 表示整個catalina的servlet引擎,多數(shù)情況下包含一個或多個子容器,這些子容器要么是Host,要么是Context實現(xiàn),或者是其他自定義組。

Host - 表示包含多個Context的虛擬主機的。

Context — 表示一個ServletContext,表示一個webapp,它通常包含一個或多個wrapper。

Wrapper - 表示一個servlet定義的(如果servlet本身實現(xiàn)了SingleThreadModel,則可能支持多個servlet實例)。

結(jié)合整體的框架圖中上述組件部分,我們看下包含了什么?

很明顯,除了四個組件的嵌套關(guān)系,Container中還包含了Realm,Cluster,Listeners, Pipleline等支持組件。

這一點,還可以通過相關(guān)注釋可以看出:

**Loader** - Class loader to use for integrating new Java classes for this Container into the JVM in which Catalina is running.

**Logger** - Implementation of the log() method signatures of the ServletContext interface.

**Manager** - Manager for the pool of Sessions associated with this Container.

**Realm** - Read-only interface to a security domain, for authenticating user identities and their corresponding roles.

**Resources** - JNDI directory context enabling access to static resources, enabling custom linkages to existing server components when Catalina is embedded in a larger server.

# Tomcat LifeCycle機制?

Server及其它組件

Server后續(xù)組件生命周期及初始化

Server的依賴結(jié)構(gòu)

public interface Lifecycle {

/** 第1類:針對監(jiān)聽器 **/

// 添加監(jiān)聽器

public void addLifecycleListener(LifecycleListener listener);

// 獲取所以監(jiān)聽器

public LifecycleListener[] findLifecycleListeners();

// 移除某個監(jiān)聽器

public void removeLifecycleListener(LifecycleListener listener);

/** 第2類:針對控制流程 **/

// 初始化方法

public void init() throws LifecycleException;

// 啟動方法

public void start() throws LifecycleException;

// 停止方法,和start對應

public void stop() throws LifecycleException;

// 銷毀方法,和init對應

public void destroy() throws LifecycleException;

/** 第3類:針對狀態(tài) **/

// 獲取生命周期狀態(tài)

public LifecycleState getState();

// 獲取字符串類型的生命周期狀態(tài)

public String getStateName();

}

# Tomcat 中Executor?

1.Tomcat希望將Executor也納入Lifecycle生命周期管理,所以讓它實現(xiàn)了Lifecycle接口 2.引入超時機制:也就是說當work queue滿時,會等待指定的時間,如果超時將拋出RejectedExecutionException,所以這里增加了一個void execute(Runnable command, long timeout, TimeUnit unit)方法; 其實本質(zhì)上,它構(gòu)造了JUC中ThreadPoolExecutor,通過它調(diào)用ThreadPoolExecutor的void execute(Runnable command, long timeout, TimeUnit unit)方法。

# Tomcat 中的設(shè)計模式?

責任鏈模式:管道機制

在軟件開發(fā)的常接觸的責任鏈模式是FilterChain,它體現(xiàn)在很多軟件設(shè)計中:

比如HttpServletRequest處理的過濾器中

當一個request過來的時候,需要對這個request做一系列的加工,使用責任鏈模式可以使每個加工組件化,減少耦合。也可以使用在當一個request過來的時候,需要找到合適的加工方式。當一個加工方式不適合這個request的時候,傳遞到下一個加工方法,該加工方式再嘗試對request加工。

網(wǎng)上找了圖,這里我們后文將通過Tomcat請求處理向你闡述。

外觀模式:request請求 觀察者模式:事件監(jiān)聽

java中的事件機制的參與者有3種角色

Event Eource:事件源,發(fā)起事件的主體。Event Object:事件狀態(tài)對象,傳遞的信息載體,就好比Watcher的update方法的參數(shù),可以是事件源本身,一般作為參數(shù)存在于listerner 的方法之中。Event Listener:事件監(jiān)聽器,當它監(jiān)聽到event object產(chǎn)生的時候,它就調(diào)用相應的方法,進行處理。

其實還有個東西比較重要:事件環(huán)境,在這個環(huán)境中,可以添加事件監(jiān)聽器,可以產(chǎn)生事件,可以觸發(fā)事件監(jiān)聽器。

模板方式: Lifecycle

LifecycleBase是使用了狀態(tài)機+模板模式來實現(xiàn)的。模板方法有下面這幾個:

// 初始化方法

protected abstract void initInternal() throws LifecycleException;

// 啟動方法

protected abstract void startInternal() throws LifecycleException;

// 停止方法

protected abstract void stopInternal() throws LifecycleException;

// 銷毀方法

protected abstract void destroyInternal() throws LifecycleException;

柚子快報邀請碼778899分享:【開發(fā)框架和中間件】

http://yzkb.51969.com/

好文鏈接

評論可見,查看隱藏內(nèi)容

本文內(nèi)容根據(jù)網(wǎng)絡(luò)資料整理,出于傳遞更多信息之目的,不代表金鑰匙跨境贊同其觀點和立場。

轉(zhuǎn)載請注明,如有侵權(quán),聯(lián)系刪除。

本文鏈接:http://gantiao.com.cn/post/18738770.html

發(fā)布評論

您暫未設(shè)置收款碼

請在主題配置——文章設(shè)置里上傳

掃描二維碼手機訪問

文章目錄