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

Spring?question問(wèn)題小結(jié)

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

Spring

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

1.手動(dòng)

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

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

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

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

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

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

1、Spring

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

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

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

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

2.如果需要配置數(shù)據(jù)源和事務(wù)管理器,可以在Spring的配置文件中進(jìn)行相關(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 注解對(duì)應(yīng)的數(shù)據(jù)訪問(wèn)異常轉(zhuǎn)化功能,可以配置相關(guān)的異常轉(zhuǎn)化器。示例如下:

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

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

2、Spring Boot

在使用Spring Boot時(shí),可以省略繁瑣的配置過(guò)程,因?yàn)镾pring Boot提供了自動(dòng)配置的功能。對(duì)于@Repository注解的配置,可以按照以下步驟進(jìn)行:

  • 在Spring Boot主類上添加 @SpringBootApplication 注解,該注解包含了 @EnableAutoConfiguration 注解,用于開(kāi)啟自動(dòng)配置功能。
  • 確保@Repository注解所在的包或子包在主類的掃描范圍內(nèi),可以通過(guò) @ComponentScan 注解進(jìn)行配置,或者將主類放在包的頂層位置。
  • 如果需要配置數(shù)據(jù)源,可以在 application.properties application.yml 配置文件中添加相關(guān)的配置項(xiàng),如下所示:
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會(huì)根據(jù)配置文件的內(nèi)容自動(dòng)配置數(shù)據(jù)源。

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

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

Q3:@Repository有什么用

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

@Repository的作用主要有以下幾點(diǎn):

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

Q4:談?wù)剬?duì)IoC的理解

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

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

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

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

Q6:注入Bean的注解

  • @Autowired
  • @Resource
  • @Inject

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

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

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

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

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

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

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

總結(jié)一下:

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

Q8:Bean的作用域

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

Q9:為什么在Spring boot沒(méi)有配置 bean 的作用域

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

二. 面向切面編程(AOP)

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

Q1:談?wù)剬?duì)AOP的理解

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

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

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

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

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");
    }
}

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

Q2:為什么要對(duì)Spring AOP進(jìn)行代理,不代理會(huì)怎樣?

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

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

public class AlphaAspect {    
@Pointcut("execution(* com.newcoder.community.service.*.*(..))")//所有類、所有方法   
public void pointcut(){}
@Before("pointcut()")//連接點(diǎn)開(kāi)始記日志
public void before(){
    System.out.println("before");
}
@After("pointcut()")//連接點(diǎn)后記日志
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í)行代理對(duì)象,織入代理對(duì)象,用來(lái)代替原始對(duì)象
public Object around(ProceedingJoinPoint joinPoint) throws Throwable{//ProceedingJoinPoint為連接點(diǎn),織入部位
    System.out.println("around before");
    Object obj = joinPoint.proceed();//proceed調(diào)目標(biāo)主鍵 調(diào)用原始對(duì)象方法
    System.out.println("around after");
    return obj;
}

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

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

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

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

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

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

是的,目標(biāo)對(duì)象的所有方法都可以作為連接點(diǎn)。連接點(diǎn)是程序執(zhí)行過(guò)程中的特定點(diǎn),包括方法的調(diào)用、異常的拋出、字段的訪問(wèn)等。在AOP中,最常見(jiàn)的連接點(diǎn)是方法的調(diào)用,因?yàn)槲覀兺ǔOM诜椒ǖ膱?zhí)行前、執(zhí)行后或發(fā)生異常時(shí)插入切面邏輯。 在AOP中,可以選擇在目標(biāo)對(duì)象的所有方法上織入切面邏輯,也可以選擇只在特定的方法上織入切面邏輯,這取決于所定義的切點(diǎn)(Pointcut)。切點(diǎn)是定義在哪些連接點(diǎn)上織入切面邏輯的規(guī)則,可以使用表達(dá)式或注解來(lái)定義切點(diǎn)。

Q6:切入點(diǎn)是類路徑嗎?

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

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

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

三、Spring MVC

Q1:說(shuō)說(shuō)自己對(duì)Spring MVC的了解

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

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

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

Q3:Spring MVC的工作原理

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

Q4:Handler 是什么?

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

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

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

Q5:為什么會(huì)將請(qǐng)求涉及到的攔截器和 Handler 一起封裝?

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

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

四、設(shè)計(jì)模式

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

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

五、Spring事務(wù)

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

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

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

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

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

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

Q3:MySQL怎么保證原子性?

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

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

相關(guān)文章

  • Jmeter對(duì)接口測(cè)試入?yún)?shí)現(xiàn)MD5加密

    Jmeter對(duì)接口測(cè)試入?yún)?shí)現(xiàn)MD5加密

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

    Java中的Kafka消費(fèi)者詳解

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

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

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

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

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

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

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

    Java8 Collectors.toMap的坑

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

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

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

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

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

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

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

    Java中獲取webapp路徑問(wèn)題詳解

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

最新評(píng)論