欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Spring?question問題小結(jié)

 更新時間:2023年10月08日 15:59:06   作者:奈川直子  
在AppConfig配置類中,通過@Bean注解創(chuàng)建了Service和Controller的實例,Spring會自動將這些實例納入容器的管理,并處理它們之間的依賴關(guān)系,本文給大家介紹Spring?question問題小結(jié),感興趣的朋友跟隨小編一起看看吧

Spring

一. 控制反轉(zhuǎn)(IoC)

1.手動

使用了Spring的 @Configuration @Bean 注解來明確指定了哪些類需要被納入容器的管理。在 AppConfig 配置類中,通過 @Bean 注解創(chuàng)建了 Service Controller 的實例,Spring會自動將這些實例納入容器的管理,并處理它們之間的依賴關(guān)系。

// 定義一個Service接口
public interface Service {
    void doSomething();
}
// 實現(xiàn)Service接口的具體類
public class ServiceImpl implements Service {
    @Override
    public void doSomething() {
        System.out.println("Service is doing something.");
    }
}
// 定義一個Controller類,它依賴于Service接口
public class Controller {d
    private Service service;
    // 通過構(gòu)造函數(shù)注入依賴
    public Controller(Service service) {
        this.service = service;
    }
    public void doAction() {
        service.doSomething();
    }
}
// 在應(yīng)用的入口處,使用Spring容器創(chuàng)建實例并進行依賴關(guān)系的管理
public class Main {
    public static void main(String[] args) {
        // 創(chuàng)建Spring容器
        ApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
        // 從容器中獲取Controller實例
        Controller controller = context.getBean(Controller.class);
        // 調(diào)用Controller的方法,會自動調(diào)用Service的方法
        controller.doAction();
    }
}
// 定義一個配置類,用于告訴Spring容器如何創(chuàng)建和管理Bean
@Configuration
public class AppConfig {
    @Bean
    public Service service() {
        return new ServiceImpl();
    }
    @Bean
    public Controller controller(Service service) {
        return new Controller(service);
    }
}

2.自動

SpringApplication.run(CommunityApplication.class, args) 會掃描應(yīng)用中的所有組件(包括被 @Component 、 @Service @Repository 等注解標(biāo)記的類),并將它們納入Spring容器的管理。通過調(diào)用 SpringApplication.run 方法啟動應(yīng)用,會自動創(chuàng)建一個Spring應(yīng)用上下文(ApplicationContext),并初始化整個應(yīng)用的配置和組件。

public static void main(String[] args) {
		SpringApplication.run(CommunityApplication.class, args);
	}

@SpringBootApplication 實際上是一個組合注解,包含了 @SpringBootConfiguration @EnableAutoConfiguration @ComponentScan 三個注解。其中, @SpringBootConfiguration 注解表示這是一個Spring Boot的配置類, @EnableAutoConfiguration 注解啟用自動配置, @ComponentScan 注解指定要掃描的包路徑。使用Spring Boot的自動化機制可以方便快捷地掃描和管理所有的Bean,而手動進行依賴注入可以更加精確地控制容器中的Bean。

Q1:使用@Repository注解時,怎么在Spring的配置文件中進行相關(guān)的配置?

1、Spring

在使用@Repository注解時,可以在Spring的配置文件中進行相關(guān)的配置。以下是配置步驟:

1.在Spring的配置文件中添加 context:component-scan 標(biāo)簽,用于開啟組件掃描功能,掃描帶有 @Repository 注解的類。示例如下:

<context:component-scan base-package="com.example.repository" />

其中, base-package 屬性指定了要掃描的包路徑。

2.如果需要配置數(shù)據(jù)源和事務(wù)管理器,可以在Spring的配置文件中進行相關(guān)的配置。示例如下:

<bean id="dataSource" class="org.apache.commons.dbcp2.BasicDataSource">
    <!-- 數(shù)據(jù)源相關(guān)配置 -->
</bean>
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
    <property name="dataSource" ref="dataSource" />
</bean>

其中, dataSource 是數(shù)據(jù)源的配置, transactionManager 是事務(wù)管理器的配置。

3.如果需要使用 @Repository 注解對應(yīng)的數(shù)據(jù)訪問異常轉(zhuǎn)化功能,可以配置相關(guān)的異常轉(zhuǎn)化器。示例如下:

<bean class="org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor" />

這個配置會自動為帶有 @Repository 注解的類添加異常轉(zhuǎn)化功能。通過以上配置,就可以在Spring的配置文件中配置 @Repository 注解相關(guān)的配置。注意,具體的配置內(nèi)容根據(jù)實際需求和使用的技術(shù)選擇可能會有所不同。

2、Spring Boot

在使用Spring Boot時,可以省略繁瑣的配置過程,因為Spring Boot提供了自動配置的功能。對于@Repository注解的配置,可以按照以下步驟進行:

  • 在Spring Boot主類上添加 @SpringBootApplication 注解,該注解包含了 @EnableAutoConfiguration 注解,用于開啟自動配置功能。
  • 確保@Repository注解所在的包或子包在主類的掃描范圍內(nèi),可以通過 @ComponentScan 注解進行配置,或者將主類放在包的頂層位置。
  • 如果需要配置數(shù)據(jù)源,可以在 application.properties application.yml 配置文件中添加相關(guān)的配置項,如下所示:
propertiesCopy codespring.datasource.url=jdbc:mysql://localhost:3306/mydb
spring.datasource.username=root
spring.datasource.password=123456
spring.datasource.driver-class-name=com.mysql.jdbc.Driver

這樣,Spring Boot會根據(jù)配置文件的內(nèi)容自動配置數(shù)據(jù)源。

4.如果需要事務(wù)管理器,可以在需要使用事務(wù)的類或方法上添加 @Transactional 注解,Spring Boot會自動配置事務(wù)管理器。 通過以上步驟,就可以在Spring Boot中使用@Repository注解,無需進行繁瑣的配置,Spring Boot會根據(jù)約定和自動配置的機制自動完成相關(guān)的配置。 Q2:@Primary有什么用

@Primary注解是Spring框架中的一個注解,用于標(biāo)識主要的Bean實例。當(dāng)存在多個同類型的Bean實例時,通過使用@Primary注解,可以指定其中一個Bean實例為首選的主要實例。

Q3:@Repository有什么用

@Repository注解是Spring框架中的一個注解,用于標(biāo)識持久層組件(如DAO類)。

@Repository的作用主要有以下幾點:

  • 標(biāo)識持久層組件:通過在持久層的類上添加 @Repository 注解,可以告訴Spring容器該類是一個用于數(shù)據(jù)訪問的組件。Spring在進行組件掃描時,會掃描帶有 @Repository 注解的類,并將其實例化為 Bean 。
  • 提供異常轉(zhuǎn)化功能: @Repository 注解還提供了數(shù)據(jù)訪問異常的轉(zhuǎn)化機制。當(dāng)數(shù)據(jù)訪問過程中發(fā)生異常時,Spring會將底層的數(shù)據(jù)訪問異常(如JDBC異常)轉(zhuǎn)化為Spring的統(tǒng)一異常體系,使得應(yīng)用程序可以更方便地處理和捕獲異常。
  • 具備@Component的功能: @Repository 注解是 @Component 注解的派生注解,因此 @Repository 注解具備 @Component 的所有功能。它可以被Spring容器自動掃描并裝配,可以使用 @Autowired @Resource 等注解進行依賴注入,也可以使用@Qualifier注解進行指定具體的實現(xiàn)類。

Q4:談?wù)剬oC的理解

控制:創(chuàng)建、實例化對象的權(quán)力反轉(zhuǎn):將這些權(quán)力交給IoC容器和Spring框架

將對象之間的依賴關(guān)系交給IoC容器管理,由IoC容器完成對象的注入,簡化開發(fā),IoC容器像是一個工廠,創(chuàng)建一個對象時只配置好,不需要考慮怎么被創(chuàng)建出來的。Spring中用Xml文件配置bean,在Spring Boot中用注解配置。

Q5:@Component和@Bean的區(qū)別

  • @Component注解作用于類,而@Bean注解作用于方法
  • @Component通常是通過類路徑掃描來自動偵察以及自動裝配到Spring容器中;
  • @Bean在標(biāo)有該注解的方法中定義產(chǎn)生這個bean,@Bean告訴了Spring這是某個類的實例,當(dāng)我需要的時候還給我。
  • @Bean比@Component的自定義性更強

Q6:注入Bean的注解

  • @Autowired
  • @Resource
  • @Inject

1.@Autowired 屬于 Spring 內(nèi)置的注解,默認(rèn)的注入方式是 byType(根據(jù)類型進行匹配) ,首先根據(jù)接口類型去匹配并注入 Bean 。如果一個接口有多個實現(xiàn)類,注入方式就會變?yōu)?byName(根據(jù)名稱匹配)

舉個例子, SmsService 接口有兩個實現(xiàn)類: SmsServiceImpl1 SmsServiceImpl2 ,且它們都已經(jīng)被 Spring 容器所管理。

// 報錯,byName 和 byType 都無法匹配到 bean
@Autowired
private SmsService smsService;
// 正確注入 SmsServiceImpl1 對象對應(yīng)的 bean
@Autowired
private SmsService smsServiceImpl1;
// 正確注入  SmsServiceImpl1 對象對應(yīng)的 bean
// smsServiceImpl1 就是我們上面所說的名稱
@Autowired
@Qualifier(value = "smsServiceImpl1")
private SmsService smsService;

2.@Resource 屬于 JDK 提供的注解,默認(rèn)注入方式為 byName 。如果無法通過名稱匹配到對應(yīng)的 Bean 的話,注入方式會變?yōu)?byType 。 @Resource 有兩個比較重要且日常開發(fā)常用的屬性: name (名稱)、 type (類型)。

public @interface Resource {
    String name() default "";
    Class<?> type() default Object.class;
}

如果僅指定 name 屬性則注入方式為 byName ,如果僅指定 type 屬性則注入方式為 byType ,如果同時指定 name type 屬性(不建議這么做)則注入方式為 byType + byName

// 報錯,byName 和 byType 都無法匹配到 bean
@Resource
private SmsService smsService;
// 正確注入 SmsServiceImpl1 對象對應(yīng)的 bean
@Resource
private SmsService smsServiceImpl1;
// 正確注入 SmsServiceImpl1 對象對應(yīng)的 bean(比較推薦這種方式)
@Resource(name = "smsServiceImpl1")
private SmsService smsService;

總結(jié)一下:

  • @Autowired 是 Spring 提供的注解, @Resource 是 JDK 提供的注解。
  • Autowired 默認(rèn)的注入方式為 byType (根據(jù)類型進行匹配), @Resource 默認(rèn)注入方式為 byName (根據(jù)名稱進行匹配)。
  • 當(dāng)一個接口存在多個實現(xiàn)類的情況下, @Autowired @Resource 都需要通過名稱才能正確匹配到對應(yīng)的 Bean。 Autowired 可以通過 @Qualifier 注解來顯式指定名稱, @Resource 可以通過 name 屬性來顯式指定名稱。 @Autowired 支持在構(gòu)造函數(shù)、方法、字段和參數(shù)上使用。 @Resource 主要用于字段和方法上的注入,不支持在構(gòu)造函數(shù)或參數(shù)上使用

Q8:Bean的作用域

  • Singleton:IoC容器中只有唯一的bean實例,Spring的bean默認(rèn)都是單例的。在之后的每次請求或注入時,都會返回同一個實例,而不會重新創(chuàng)建新的實例。
  • prototype:每次獲取都會創(chuàng)建一個新的 bean 實例。與默認(rèn)的單例模式不同,每次通過容器獲取prototype作用域的Bean時,都會創(chuàng)建一個新的實例。原型模式的Bean不適合進行依賴注入,因為每次注入都會得到一個新的實例,無法保證依賴關(guān)系的一致性。
  • request (僅 Web 應(yīng)用可用): 每一次 HTTP 請求都會產(chǎn)生一個新的 bean(請求 bean),該 bean 僅在當(dāng)前 HTTP request 內(nèi)有效。
  • session (僅 Web 應(yīng)用可用) : 每一次來自新 session 的 HTTP 請求都會產(chǎn)生一個新的 bean(會話 bean),該 bean 僅在當(dāng)前 HTTP session 內(nèi)有效。

Q9:為什么在Spring boot沒有配置 bean 的作用域

在Spring Boot中,為了簡化配置和提高開發(fā)效率,通常不需要顯式地配置Bean的作用域。Spring Boot默認(rèn)使用單例模式來管理Bean,即每個Bean在容器中只會存在一個實例。 這是因為Spring Boot遵循"約定優(yōu)于配置"的原則,通過自動配置和默認(rèn)配置來簡化開發(fā)過程。在大多數(shù)情況下,單例模式已經(jīng)能夠滿足開發(fā)需求,因此默認(rèn)使用單例模式可以減少不必要的配置。 如果需要使用其他作用域,如原型(prototype)、會話(session)、請求(request)等,可以在需要的地方使用特定的注解來標(biāo)記,而不需要在配置文件中顯式配置。例如,可以使用** @Scope("prototype") **注解來將特定的Bean定義為原型模式。

二. 面向切面編程(AOP)

術(shù)語含義
目標(biāo)(Target)目標(biāo)對象/被通知的對象
代理(Proxy)向目標(biāo)對象應(yīng)用通知之后創(chuàng)建的代理對象
連接點(JoinPoint)目標(biāo)對象的所屬類中,定義的所有方法均為連接點
切入點(Pointcut)被切面攔截/增強的連接點(切入點一定是連接點,連接點不一定是織入點)
通知(Advice)增強的邏輯/代碼,也是攔截到目標(biāo)對象的連接點后應(yīng)該做的事
織入(Weaving)將通知 應(yīng)用到目標(biāo)對象,產(chǎn)生代理對象的過程動作
方面主鍵(Aspect)Pointcut+Advice

Q1:談?wù)剬OP的理解

能夠?qū)⑴c業(yè)務(wù)無關(guān),卻為業(yè)務(wù)模塊所共同調(diào)用的邏輯和責(zé)任所封裝起來,例如:事務(wù)處理、權(quán)限控制,日志管理,減少重復(fù)代碼,比較好維護。

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

Spring AOP 的工作原理:自動為目標(biāo)對象生成代理,并在方法調(diào)用時織入切面邏輯。

代理對象是通過 Spring AOP 自動生成的,并且已經(jīng)被注入到 ApplicationContext 中。具體來說,代理對象是在以下代碼中獲取的:

UserService userService = context.getBean(UserService.class);
// 主類
@SpringBootApplication
public class Application {
    public static void main(String[] args) {
        ApplicationContext context = SpringApplication.run(Application.class, args);
        UserService userService = context.getBean(UserService.class);
        userService.addUser("john", "123456");
    }
}

在這個示例中,通過 ApplicationContext getBean 方法來獲取代理對象。根據(jù) Spring AOP 的配置,如果 UserService 接口被代理,那么獲取到的 userService 對象就是代理對象;如果 UserServiceImpl 類被代理,那么獲取到的 userService 對象也是代理對象。

Q2:為什么要對Spring AOP進行代理,不代理會怎樣?

Spring AOP 中,代理是實現(xiàn)切面功能的關(guān)鍵。如果不進行代理,切面邏輯將無法被織入到目標(biāo)對象的方法調(diào)用中,失去了 AOP 的作用。 具體來說,代理對象在目標(biāo)對象和調(diào)用方之間充當(dāng)了一個中間層。當(dāng)調(diào)用方調(diào)用代理對象的方法時,代理對象會在方法執(zhí)行前后執(zhí)行切面邏輯。這樣,我們可以在切面中添加一些額外的邏輯,比如日志記錄、事務(wù)管理、性能監(jiān)控等。代理對象將切面邏輯織入到目標(biāo)對象的方法調(diào)用中,從而實現(xiàn)了橫切關(guān)注點的模塊化。 如果不進行代理,切面邏輯將無法被自動應(yīng)用到目標(biāo)對象的方法調(diào)用中。這意味著我們需要在每個目標(biāo)對象方法的調(diào)用處手動添加切面邏輯,這樣會導(dǎo)致代碼的重復(fù)和冗余,不利于代碼的維護和擴展。而代理機制可以自動為目標(biāo)對象生成代理,并在方法調(diào)用時織入切面邏輯,使得切面的應(yīng)用更加便捷和靈活。 除了將切面邏輯織入到方法調(diào)用中,代理還可以實現(xiàn)其他功能,比如延遲加載、事務(wù)管理、緩存等。代理對象可以攔截方法調(diào)用,根據(jù)需要進行一些額外的處理,從而提供更多的功能。

Q3:那在以下代碼中,誰是目標(biāo)對象,誰是代理對象,誰是調(diào)用方?

public class AlphaAspect {    
@Pointcut("execution(* com.newcoder.community.service.*.*(..))")//所有類、所有方法   
public void pointcut(){}
@Before("pointcut()")//連接點開始記日志
public void before(){
    System.out.println("before");
}
@After("pointcut()")//連接點后記日志
public void after(){
    System.out.println("after");
}
@AfterReturning("pointcut()")//有返回值后記日志
public void afterReturn(){
    System.out.println("afterReturn");
}
@AfterThrowing("pointcut()")//拋異常后記日志
public void afterThrowing(){
    System.out.println("afterThrowing");
}
@Around("pointcut()")//前后都織入  執(zhí)行代理對象,織入代理對象,用來代替原始對象
public Object around(ProceedingJoinPoint joinPoint) throws Throwable{//ProceedingJoinPoint為連接點,織入部位
    System.out.println("around before");
    Object obj = joinPoint.proceed();//proceed調(diào)目標(biāo)主鍵 調(diào)用原始對象方法
    System.out.println("around after");
    return obj;
}

在這個例子中,目標(biāo)對象是com.newcoder.community.service包下的所有類的所有方法。 AlphaAspect類本身是一個切面類,其中包含了各種注解標(biāo)記的通知方法。這些通知方法會在目標(biāo)對象的方法調(diào)用前后執(zhí)行相應(yīng)的邏輯。因此,AlphaAspect類是代理對象。 調(diào)用方是在業(yè)務(wù)代碼中調(diào)用目標(biāo)對象的方法的地方,這個例子中沒有給出具體的業(yè)務(wù)代碼,所以無法確定調(diào)用方是什么。

所以,代理對象會在目標(biāo)對象的方法調(diào)用前后執(zhí)行相應(yīng)的邏輯。

Q4:那為什么說向目標(biāo)對象應(yīng)用通知之后創(chuàng)建代理對象?

在AOP中,通知(Advice)是切面的核心邏輯,用于在目標(biāo)對象的方法調(diào)用前后執(zhí)行特定的操作。為了將通知應(yīng)用到目標(biāo)對象的方法調(diào)用中,需要創(chuàng)建代理對象來包裝目標(biāo)對象。代理對象負責(zé)攔截目標(biāo)對象的方法調(diào)用,并在適當(dāng)?shù)臅r機執(zhí)行通知。 代理對象的創(chuàng)建過程可以分為兩種方式:靜態(tài)代理和動態(tài)代理。

  • 靜態(tài)代理:在編譯時就已經(jīng)將切面邏輯與目標(biāo)對象織入到了一起,生成了代理類的字節(jié)碼文件。代理對象是在編譯時生成的,不需要在運行時再去創(chuàng)建。
  • (AspectJ)動態(tài)代理:在運行時動態(tài)地生成代理對象。動態(tài)代理需要借助于Java的反射機制來實現(xiàn)。通過動態(tài)創(chuàng)建代理對象,可以根據(jù)切面的配置在運行時將通知應(yīng)用到目標(biāo)對象的方法調(diào)用中。 在Spring AOP中,默認(rèn)使用的是動態(tài)代理。Spring使用JDK動態(tài)代理和CGLIB動態(tài)代理兩種方式來創(chuàng)建代理對象。如果目標(biāo)對象實現(xiàn)了接口,則使用JDK動態(tài)代理;如果目標(biāo)對象沒有實現(xiàn)接口,則使用CGLIB動態(tài)代理。 無論是靜態(tài)代理還是動態(tài)代理,代理對象的創(chuàng)建都是在應(yīng)用通知之后進行的。通過代理對象,切面邏輯可以被織入到目標(biāo)對象的方法調(diào)用中,實現(xiàn)對目標(biāo)對象的增強。

Q5:目標(biāo)對象所有的方法就是連接點嗎?

是的,目標(biāo)對象的所有方法都可以作為連接點。連接點是程序執(zhí)行過程中的特定點,包括方法的調(diào)用、異常的拋出、字段的訪問等。在AOP中,最常見的連接點是方法的調(diào)用,因為我們通常希望在方法的執(zhí)行前、執(zhí)行后或發(fā)生異常時插入切面邏輯。 在AOP中,可以選擇在目標(biāo)對象的所有方法上織入切面邏輯,也可以選擇只在特定的方法上織入切面邏輯,這取決于所定義的切點(Pointcut)。切點是定義在哪些連接點上織入切面邏輯的規(guī)則,可以使用表達式或注解來定義切點。

Q6:切入點是類路徑嗎?

不,切入點(Pointcut)并不是類路徑。切入點是在 AOP 用于定義哪些連接點(JoinPoint)應(yīng)該被織入切面邏輯的規(guī)則。 切入點可以使用表達式或注解來定義。使用表達式定義切入點時,可以使用 AspectJ 風(fēng)格的切入點表達式,如 execution、within、args 等關(guān)鍵字,以及類、方法、參數(shù)等信息來描述需要織入切面邏輯的連接點。使用注解來定義切入點時,可以通過在目標(biāo)對象的方法上添加特定的注解,然后通過切入點表達式來匹配這些注解來確定要織入切面邏輯的連接點。 切入點可以非常靈活地定義,可以選擇在目標(biāo)對象的所有方法上織入切面邏輯,也可以選擇只在特定的方法或類上織入切面邏輯。切入點的定義是根據(jù)業(yè)務(wù)需求和設(shè)計目標(biāo)來確定的,通常會根據(jù)實際情況來選擇需要織入切面邏輯的連接點。

Q7:織入的過程是不是就相當(dāng)于動態(tài)代理和靜態(tài)代理過程?

? 是的,織入的過程可以類比為動態(tài)代理和靜態(tài)代理的過程。? 在靜態(tài)代理中,代理對象和目標(biāo)對象實現(xiàn)同一個接口,代理對象在調(diào)用目標(biāo)對象方法的前后插入額外的邏輯。這種方式需要在編譯時期就確定代理關(guān)系,并在代碼中顯式地指定代理對象。? 在動態(tài)代理中,代理對象是在運行時動態(tài)生成的,無需事先編寫代理類。通過Java的反射機制,動態(tài)代理可以在運行時攔截并處理目標(biāo)對象的方法調(diào)用。在動態(tài)代理中,我們可以在目標(biāo)對象方法的調(diào)用前后插入切面邏輯。? 類似地, AOP 的織入過程也是在運行時動態(tài)生成的。 AOP 框架會根據(jù)切入點的定義,對目標(biāo)對象的方法調(diào)用進行攔截,并根據(jù)切面邏輯對其進行增強。這個過程可以看作是在運行時動態(tài)代理的過程。 不同的是,動態(tài)代理和靜態(tài)代理通常是針對單個類或?qū)ο筮M行的,而** AOP 的織入可以同時作用于多個類和對象**,根據(jù)切入點的定義對滿足條件的連接點進行增強。

三、Spring MVC

Q1:說說自己對Spring MVC的了解

MVC是模型(Model)、視圖(View)、控制器(Controller)的簡寫,它是通過將業(yè)務(wù)邏輯、數(shù)據(jù)、顯示分離組織代碼。

Q2:Spring MVC的核心組件有哪些?

  • DispatcherServlet 核心的中央處理器,負責(zé)接受請求、分發(fā),并給予客戶響應(yīng)
  • HandlerMapping 處理器映射器,根據(jù)URL去匹配查找能處理的 Handler ,并會將請求涉及到的攔截器和 Handler 一起封裝
  • HandlerAdapter 處理器適配器 ,根據(jù) HandlerMapping 找到的 Handler ,適配執(zhí)行對應(yīng)的 Handler .
  • Handler 請求處理器,處理實際請求的處理器
  • ViewResolver 視圖解析器,根據(jù) Handler 返回的邏輯視圖,解析并渲染真正的視圖,并傳遞給DispatcherServlet響應(yīng)客戶端

Q3:Spring MVC的工作原理

  • 客戶端發(fā)送請求, DispatcherServlet 攔截請求 DispatcherServlet 根據(jù)請求信息調(diào)用 HandlerMapping 。
  • HandlerMapping 根據(jù)URL去匹配查找能處理的
  • Handler ,并會將涉及到的攔截器和 Handler 一起封裝
  • DispatcherServlet 調(diào)用 HandlerAdapter 適配器執(zhí)行 Handler Handler 完成對用戶的請求的處理,返回一個 ModelAndView 對象給 DispatcherServlet
  • ViewResolver 根據(jù)邏輯 View 查找實際的 View DispatcherServlet 把返回的 Model 傳給 View
  • View 返回客戶端

Q4:Handler 是什么?

Handler 是指在 Spring MVC 框架中用于處理用戶請求的組件。Handler 可以是一個 Controller 類中的方法、一個 Servlet、一個 WebSocket 處理器或其他可處理請求的組件。

Q5:DispatcherServlet 為什么調(diào)用 HandlerAdapter適配器執(zhí)行 Handler?

不同的 Handler 可能有不同的處理方式,例如一個 Controller 方法、一個 Servlet、一個 WebSocket 處理器等。為了統(tǒng)一處理不同類型的 Handler,需要使用適配器模式將不同類型的 Handler 適配為統(tǒng)一的處理方式。 HandlerAdapter 適配器的作用就是根據(jù)不同類型的 Handler,將請求信息進行適配,使其能夠被統(tǒng)一調(diào)用并執(zhí)行。它根據(jù) Handler 的類型,調(diào)用相應(yīng)的適配方法,將請求信息傳遞給 Handler 進行處理,并獲取處理結(jié)果返回給 DispatcherServlet。 通過使用 HandlerAdapter 適配器,DispatcherServlet 不需要關(guān)心具體的 Handler 類型,只需要調(diào)用適配器的方法即可,實現(xiàn)了對不同類型 Handler 的統(tǒng)一調(diào)用和處理。

Q5:為什么會將請求涉及到的攔截器和 Handler 一起封裝?

將請求涉及到的攔截器和Handler一起封裝的目的是為了在請求處理過程中能夠方便地對請求進行攔截和處理。 攔截器是用于對請求進行預(yù)處理和后處理的組件,可以在請求到達Controller之前和之后執(zhí)行額外的邏輯。通過將攔截器和Handler一起封裝,可以實現(xiàn)以下幾個方面的功能:

  • 統(tǒng)一管理攔截器:將攔截器和Handler一起封裝,可以方便地統(tǒng)一管理攔截器的配置和使用。在配置文件或注解中指定攔截器的順序和范圍,可以靈活地控制攔截器的執(zhí)行順序和作用范圍。
  • 方便攔截器的調(diào)用:將攔截器和Handler一起封裝后,可以在請求到達Controller之前和之后分別調(diào)用攔截器的預(yù)處理和后處理方法。這樣可以方便地對請求進行攔截和處理,執(zhí)行一些通用的操作,如權(quán)限驗證、日志記錄等。
  • 提高代碼的復(fù)用性:將一些通用的邏輯處理抽離出來作為攔截器,通過封裝攔截器和Handler,可以在多個請求處理過程中共享這些邏輯,提高代碼的復(fù)用性。例如,多個請求需要進行權(quán)限驗證,可以將權(quán)限驗證的邏輯抽象為一個攔截器,在多個請求處理過程中共享使用。
  • 靈活控制請求處理流程:通過封裝攔截器和Handler,可以靈活控制請求處理流程。在攔截器的預(yù)處理方法中,可以決定是否繼續(xù)處理請求,或者進行一些重定向或錯誤處理操作。在攔截器的后處理方法中,可以對響應(yīng)結(jié)果進行進一步的處理或修改。

四、設(shè)計模式

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

  • 工廠模式:通過beanFactory、ApplicationContext創(chuàng)建bean對象
  • 代理模式:Spring AOP功能的實現(xiàn)
  • 單例模式:Spring的bean默認(rèn)都是單例的
  • 適配器模式:Spring MVC用到了適配器模式適配handler、Spring AOP的Advice用到了適配器模式適配成MethodInterceptor接口類型的對象(全都變成方法攔截器對象)
  • 模板模式:以Template結(jié)尾的對數(shù)據(jù)庫操作的類
  • 包裝器模式:項目需要連接多個數(shù)據(jù)庫,不同的客戶每次訪問可能會訪問不同的數(shù)據(jù)庫。包裝器模式可動態(tài)的切換不同數(shù)據(jù)源。

五、Spring事務(wù)

Q1:事務(wù)的特性(ACID)了解嗎?

  • 原子性:事務(wù)是最小的執(zhí)行單位,不允許分割,事物的原子性確保動作要么全部完成,要么不起作用
  • 一致性:執(zhí)行事務(wù)前后,數(shù)據(jù)保持一致,例如轉(zhuǎn)賬時,無論事務(wù)是否成功,轉(zhuǎn)賬人和收款人的總額應(yīng)該是不變的
  • 隔離性:并發(fā)訪問數(shù)據(jù)庫時,一個用戶的事務(wù)不被其他事務(wù)所干擾,各并發(fā)事務(wù)之間的數(shù)據(jù)庫是獨立的
  • 持久性:一個事務(wù)被提交以后,他對數(shù)據(jù)庫的改變是持久的,數(shù)據(jù)庫發(fā)生故障也不應(yīng)該對它有任何影響

只有保證了原子性、隔離性、持久性以后,一致性才能得到保障:AID->C

Q2:什么時候才用事務(wù)的隔離性?

事務(wù)的隔離性是指多個事務(wù)并發(fā)執(zhí)行時,各個事務(wù)之間的數(shù)據(jù)應(yīng)該是相互隔離的,一個事務(wù)的操作不應(yīng)該對其他事務(wù)的操作產(chǎn)生影響。在并發(fā)環(huán)境下,如果多個事務(wù)同時訪問和修改共享數(shù)據(jù),可能會導(dǎo)致數(shù)據(jù)不一致的問題。 舉個例子來說明事務(wù)的隔離性的使用場景: 假設(shè)有一個電商平臺,用戶可以在平臺上購買商品,而商品的庫存是需要管理的。當(dāng)用戶購買商品時,會進行庫存的扣減操作。在這個場景中,如果不考慮事務(wù)的隔離性,可能會出現(xiàn)以下問題:

非隔離性導(dǎo)致的庫存錯誤:假設(shè)有兩個用戶 A 和 B 同時購買同一件商品,且?guī)齑嬷挥幸患?。如果不使用事?wù)的隔離性,A 和 B 同時發(fā)起購買請求時,在沒有互斥控制的情況下,可能會導(dǎo)致庫存扣減錯誤。例如,A 和 B 同時讀取庫存數(shù)量為 1,然后都進行庫存扣減,最終庫存可能會變成 -1。 為了解決這個問題,可以使用事務(wù)的隔離性。通過將庫存扣減操作放在一個事務(wù)中,并使用合適的隔離級別,可以避免并發(fā)訪問時的數(shù)據(jù)不一致問題。例如,使用數(shù)據(jù)庫的隔離級別 SERIALIZABLE,可以確保同一時間只有一個事務(wù)能夠訪問和修改庫存數(shù)據(jù),從而避免庫存錯誤問題。

Q3:MySQL怎么保證原子性?

保證原子性,就要在異常發(fā)生的時候?qū)σ呀?jīng)執(zhí)行的操作進行回滾,在MySQL中,恢復(fù)機制是通過回滾日志實現(xiàn)的,所有事務(wù)進行的修改都會先記錄到這個回滾日志中,然后再執(zhí)行相關(guān)的操作。如果執(zhí)行過程中出現(xiàn)異常,就利用回滾日志中的信息將數(shù)據(jù)回滾到修改之前的樣子。并且,回滾日志會先把數(shù)據(jù)持久化到硬盤上,這樣就能保證數(shù)據(jù)庫在事務(wù)執(zhí)行過程中宕機,未完成的事務(wù)會自動回滾。當(dāng)再次打開數(shù)據(jù)庫時,數(shù)據(jù)庫會通過回滾日志來查找未完成的事務(wù),并對其進行回滾操作,以保證數(shù)據(jù)的一致性。

到此這篇關(guān)于Spring question問題小結(jié)的文章就介紹到這了,更多相關(guān)Spring question內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Jmeter對接口測試入?yún)崿F(xiàn)MD5加密

    Jmeter對接口測試入?yún)崿F(xiàn)MD5加密

    這篇文章主要介紹了Jmeter對接口測試入?yún)崿F(xiàn)MD5加密,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下
    2020-08-08
  • Java中的Kafka消費者詳解

    Java中的Kafka消費者詳解

    這篇文章主要介紹了Java中的Kafka消費者詳解,Kafka是一個分布式流行消息系統(tǒng),通常用于大規(guī)模數(shù)據(jù)處理和實時數(shù)據(jù)流應(yīng)用程序,它具有高吞吐量、可擴展性和容錯性的特點,需要的朋友可以參考下
    2023-09-09
  • 基于SpringBoot實現(xiàn)QQ郵箱驗證碼注冊功能

    基于SpringBoot實現(xiàn)QQ郵箱驗證碼注冊功能

    QQ 郵箱是由騰訊公司推出的一款免費郵箱服務(wù),它提供了完整的郵件發(fā)送和接收功能,并且還支持多種郵件格式和附件類型,QQ 郵箱還具有強大的反垃圾郵件功能,可以有效地過濾垃圾郵件,并保護用戶隱私和安全,所以本文給大家介紹了基于SpringBoot實現(xiàn)QQ郵箱驗證碼注冊功能
    2024-11-11
  • Mybatis-plus實現(xiàn)主鍵自增和自動注入時間的示例代碼

    Mybatis-plus實現(xiàn)主鍵自增和自動注入時間的示例代碼

    這篇文章主要介紹了Mybatis-plus實現(xiàn)主鍵自增和自動注入時間的示例代碼,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-07-07
  • java實現(xiàn)讀取txt文件中的內(nèi)容

    java實現(xiàn)讀取txt文件中的內(nèi)容

    本文通過一個具體的例子向大家展示了如何使用java實現(xiàn)讀取TXT文件里的內(nèi)容的方法以及思路,有需要的小伙伴可以參考下
    2016-03-03
  • Java8 Collectors.toMap的坑

    Java8 Collectors.toMap的坑

    這篇文章主要介紹了Java8 Collectors.toMap的坑,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2021-03-03
  • Java遞歸實現(xiàn)字符串全排列與全組合

    Java遞歸實現(xiàn)字符串全排列與全組合

    這篇文章主要為大家詳細介紹了Java遞歸實現(xiàn)字符串全排列與全組合,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2018-02-02
  • Java數(shù)據(jù)類型轉(zhuǎn)換詳解

    Java數(shù)據(jù)類型轉(zhuǎn)換詳解

    這篇文章主要講解Java中基本數(shù)據(jù)類型、字符串與其它數(shù)據(jù)類型以及常見的日期類型的轉(zhuǎn)換,希望能給大家做一個參考。
    2016-06-06
  • Java 中引入內(nèi)部類的意義?

    Java 中引入內(nèi)部類的意義?

    這篇文章主要介紹了Java 中引入內(nèi)部類的意義?文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,,需要的朋友可以參考下
    2019-06-06
  • Java中獲取webapp路徑問題詳解

    Java中獲取webapp路徑問題詳解

    這篇文章主要介紹了Java中獲取webapp路徑問題詳解,WebApp是指基于Web的?系統(tǒng)和?應(yīng)用,其作用是向廣大的最終用戶發(fā)布一組復(fù)雜的內(nèi)容和功能,本文詳解了關(guān)于獲取路徑時候可能出現(xiàn)的問題,需要的朋友可以參考下
    2023-07-07

最新評論