国产亚洲精品福利在线无卡一,国产精久久一区二区三区,亚洲精品无码国模,精品久久久久久无码专区不卡

當(dāng)前位置: 首頁(yè) > news >正文

有什么網(wǎng)站可以做初中試題sem是什么崗位

有什么網(wǎng)站可以做初中試題,sem是什么崗位,蘇州品牌網(wǎng)站設(shè)計(jì)開(kāi)發(fā),網(wǎng)站建設(shè)個(gè)人工作總結(jié)目錄 如何實(shí)現(xiàn)一個(gè)IOC容器? 說(shuō)說(shuō)你對(duì)Spring 的理解? 你覺(jué)得Spring的核心是什么? 說(shuō)一下使用spring的優(yōu)勢(shì)? Spring是如何簡(jiǎn)化開(kāi)發(fā)的? IOC 運(yùn)行時(shí)序 prepareRefresh() 初始化上下文環(huán)境 obtainFreshBeanFactory() 創(chuàng)建并…

目錄

如何實(shí)現(xiàn)一個(gè)IOC容器?

說(shuō)說(shuō)你對(duì)Spring 的理解?

你覺(jué)得Spring的核心是什么?

說(shuō)一下使用spring的優(yōu)勢(shì)?

Spring是如何簡(jiǎn)化開(kāi)發(fā)的?

IOC 運(yùn)行時(shí)序

prepareRefresh()??初始化上下文環(huán)境

obtainFreshBeanFactory()? ?創(chuàng)建并初始化 BeanFactory

prepareBeanFactory(beanFactory)??填充 BeanFactory 功能

postProcessBeanFactory()??提供子類覆蓋的額外處理

invokeBeanFactoryPostProcessors()? ? 激活各種BeanFactory處理器

registerBeanPostProcessors

initMessageSource

initApplicationEventMulticaster

onRefresh

registerListeners

finishBeanFactoryInitialization

finishRefresh

Spring的AOP的底層實(shí)現(xiàn)原理

說(shuō)說(shuō)你對(duì)Aop的理解?

說(shuō)說(shuō)你對(duì)IOC的理解?

依賴注入DI 的概念

談一下spring IOC的底層實(shí)現(xiàn)

BeanFactory和ApplicationContext有什么區(qū)別

簡(jiǎn)述spring bean的生命周期?

spring支持的bean作用域有哪些?

Spring框架中的單例Bean是線程安全的么?

spring框架中使用了哪些設(shè)計(jì)模式及應(yīng)用場(chǎng)景

spring事務(wù)的實(shí)現(xiàn)方式原理是什么?

Transaction失效

spring事務(wù)的隔離級(jí)別有哪些?

spring的事務(wù)傳播機(jī)制是什么?

spring事務(wù)什么時(shí)候會(huì)失效?

什么的是bean的自動(dòng)裝配,它有哪些方式?

spring是如何解決循環(huán)依賴的

不能解決的幾種循環(huán)依賴

pring中常見(jiàn)的幾種注解

spring、springmvc、springboot的區(qū)別是什么?

springmvc工作流程是什么?

springmvc的九大組件有哪些?

Spring框架中有哪些不同類型的事件


如何實(shí)現(xiàn)一個(gè)IOC容器?

要實(shí)現(xiàn)一個(gè)簡(jiǎn)單的Spring框架IOC容器,您可以遵循以下步驟:

  1. 定義Bean注解: 創(chuàng)建一個(gè)自定義的注解,例如@MyBean,用于標(biāo)識(shí)需要被IOC容器管理的Bean類。

  2. 掃描并解析Bean定義:(BeanDefinition) 創(chuàng)建一個(gè)Bean解析器,用于掃描應(yīng)用程序中的所有類,解析帶有@MyBean注解的類,并存儲(chǔ)Bean的定義信息,如類名、屬性等。

  3. 創(chuàng)建Bean實(shí)例: 根據(jù)Bean定義信息,使用反射機(jī)制實(shí)例化Bean,并進(jìn)行依賴注入。遍歷所有的Bean定義,根據(jù)類名使用反射創(chuàng)建Bean實(shí)例,并解析其屬性依賴關(guān)系,將相應(yīng)的依賴注入到實(shí)例中。

  4. 實(shí)現(xiàn)依賴注入: 當(dāng)創(chuàng)建Bean實(shí)例時(shí),解析Bean的屬性依賴關(guān)系,并根據(jù)依賴注入的方式,通過(guò)反射或者setter方法將需要的依賴注入到Bean實(shí)例中。

  5. 管理Bean的生命周期: 可以在Bean中定義初始化和銷毀方法,并在容器中調(diào)用這些方法來(lái)管理Bean的生命周期。可以使用@PostConstruct注解標(biāo)注初始化方法,使用@PreDestroy注解標(biāo)注銷毀方法。

  6. 提供獲取Bean的方法: 在IOC容器中提供一個(gè)方法,根據(jù)Bean的名稱獲取對(duì)應(yīng)的實(shí)例??梢允褂肕ap來(lái)存儲(chǔ)Bean實(shí)例,key為Bean的名稱,value為實(shí)例對(duì)象。

  7. 實(shí)現(xiàn)配置文件加載: 可以實(shí)現(xiàn)一個(gè)簡(jiǎn)單的配置文件加載機(jī)制,從配置文件中讀取需要注入的屬性值,例如使用properties文件或者XML文件。

以上是一個(gè)簡(jiǎn)單的實(shí)現(xiàn)Spring框架IOC容器的步驟。在實(shí)際的Spring框架中,還有更多復(fù)雜的功能和特性,如AOP、循環(huán)依賴處理、Bean的作用域、配置文件的自動(dòng)裝配等。這些是更高級(jí)的功能,需要更復(fù)雜的設(shè)計(jì)和實(shí)現(xiàn)。但通過(guò)上述步驟,您可以實(shí)現(xiàn)一個(gè)簡(jiǎn)單的IOC容器,理解IOC的基本概念和實(shí)現(xiàn)原理。

說(shuō)說(shuō)你對(duì)Spring 的理解?

官網(wǎng)地址:Spring Framework

壓縮包下載地址:JFrog

源碼地址:GitHub - spring-projects/spring-framework: Spring Framework

Spring makes it easy to create Java enterprise applications. It provides everything you need to embrace the Java language in an enterprise environment, with support for Groovy and Kotlin as alternative languages on the JVM, and with the flexibility to create many kinds of architectures depending on an application’s needs. As of Spring Framework 5.1, Spring requires JDK 8+ (Java SE 8+) and provides out-of-the-box support for JDK 11 LTS. Java SE 8 update 60 is suggested as the minimum patch release for Java 8, but it is generally recommended to use a recent patch release.
?
Spring supports a wide range of application scenarios. In a large enterprise, applications often exist for a long time and have to run on a JDK and application server whose upgrade cycle is beyond developer control. Others may run as a single jar with the server embedded, possibly in a cloud environment. Yet others may be standalone applications (such as batch or integration workloads) that do not need a server.
?
Spring is open source. It has a large and active community that provides continuous feedback based on a diverse range of real-world use cases. This has helped Spring to successfully evolve over a very long time.
?
Spring 是一個(gè)開(kāi)源的輕量級(jí)企業(yè)應(yīng)用開(kāi)發(fā)框架,它提供了廣泛的基礎(chǔ)設(shè)施支持和生命周期管理,用于幫助開(kāi)發(fā)人員構(gòu)建企業(yè)級(jí)應(yīng)用程序。以下是我對(duì) Spring 的理解:1. IoC(Inverse of Control,控制反轉(zhuǎn))容器: Spring 使用 IoC 容器管理應(yīng)用程序中的對(duì)象依賴關(guān)系,通過(guò)將對(duì)象的創(chuàng)建、配置和組裝過(guò)程由開(kāi)發(fā)者轉(zhuǎn)移到 Spring 容器,降低了組件之間的耦合度。2. AOP(Aspect-Oriented Programming,面向切面編程)支持: Spring 提供了 AOP 配置和支持,可以將橫切關(guān)注點(diǎn)(cross-cutting concerns)從核心業(yè)務(wù)邏輯中分離出來(lái),實(shí)現(xiàn)了橫切關(guān)注點(diǎn)的重用和集中管理。3. **聲明式事務(wù)管理:** Spring 提供了強(qiáng)大的事務(wù)管理支持,可以通過(guò)聲明式的方式管理事務(wù),簡(jiǎn)化了事務(wù)管理的實(shí)現(xiàn),同時(shí)提供了靈活性和可定制性。4. 模塊化設(shè)計(jì): Spring 框架被設(shè)計(jì)為多個(gè)模塊組成,每個(gè)模塊都提供了特定的功能,開(kāi)發(fā)者可以根據(jù)需求選擇使用相應(yīng)模塊,從而減少了不必要的資源浪費(fèi)。5. 簡(jiǎn)化企業(yè)級(jí)開(kāi)發(fā): Spring 提供了大量的企業(yè)級(jí)功能的封裝和支持,如數(shù)據(jù)訪問(wèn)、事務(wù)管理、安全性、消息傳遞等,大大簡(jiǎn)化了開(kāi)發(fā)人員構(gòu)建企業(yè)級(jí)應(yīng)用程序的工作量。6. 持續(xù)演進(jìn)和創(chuàng)新: Spring 框架不斷進(jìn)行演進(jìn)和創(chuàng)新,持續(xù)引入新的功能和特性,以適應(yīng)不斷變化的開(kāi)發(fā)需求和技術(shù)趨勢(shì)??偟膩?lái)說(shuō),Spring 框架提供了一套全面且靈活的解決方案,幫助開(kāi)發(fā)人員簡(jiǎn)化企業(yè)級(jí)應(yīng)用程序的開(kāi)發(fā)和維護(hù)工作,提高了代碼的可維護(hù)性、可測(cè)試性和整體質(zhì)量。通過(guò)合理使用 Spring 框架,開(kāi)發(fā)人員可以專注于業(yè)務(wù)邏輯的實(shí)現(xiàn),而不必過(guò)多關(guān)注底層技術(shù)細(xì)節(jié)。

你覺(jué)得Spring的核心是什么?

Spring是一個(gè)開(kāi)源的Java框架,用于構(gòu)建企業(yè)級(jí)的應(yīng)用程序。它提供了一個(gè)容器,用于管理應(yīng)用程序中的對(duì)象(如依賴注入)并提供了許多常用的功能和擴(kuò)展,使開(kāi)發(fā)人員能夠更加專注于業(yè)務(wù)邏輯的實(shí)現(xiàn)而不必關(guān)注太多的底層細(xì)節(jié)。

Spring的核心特性包括:

  1. 控制反轉(zhuǎn)(IoC):Spring使用控制反轉(zhuǎn)來(lái)實(shí)現(xiàn)依賴注入??刂品崔D(zhuǎn)意味著對(duì)于對(duì)象的創(chuàng)建和依賴關(guān)系的管理由容器來(lái)完成,而不是由開(kāi)發(fā)人員手動(dòng)處理。這種方式可以降低組件之間的耦合度,并且使得代碼更加靈活和易于擴(kuò)展。

  2. 面向切面編程(AOP):Spring提供了面向切面編程的支持,可以通過(guò)AOP將橫切關(guān)注點(diǎn)(如日志、事務(wù)管理)從業(yè)務(wù)邏輯中分離出來(lái),使得代碼更具可維護(hù)性和可讀性。

  3. 集成框架:Spring可以與各種其他框架和技術(shù)進(jìn)行集成,如持久化框架(Hibernate、MyBatis)、消息隊(duì)列(ActiveMQ、RabbitMQ)、Web框架(Spring MVC)等,以便于開(kāi)發(fā)人員在項(xiàng)目中使用更多的功能和工具。

總之,Spring框架提供了一種靈活、高效的開(kāi)發(fā)方式,可以幫助開(kāi)發(fā)人員構(gòu)建可擴(kuò)展、可維護(hù)的企業(yè)級(jí)應(yīng)用程序。它的特性和擴(kuò)展使得它在Java開(kāi)發(fā)社區(qū)中非常流行和廣泛使用。

說(shuō)一下使用spring的優(yōu)勢(shì)?

使用Spring框架具有許多優(yōu)勢(shì),它是一個(gè)強(qiáng)大的企業(yè)級(jí)應(yīng)用程序開(kāi)發(fā)框架,提供了廣泛的功能和特性。下面是一些使用Spring框架的優(yōu)勢(shì):

  1. 面向切面編程(AOP):Spring支持AOP,使你能夠以聲明性的方式處理跨多個(gè)模塊的關(guān)注點(diǎn)(例如事務(wù)管理、安全性、日志記錄等),提高了代碼的模塊化和可維護(hù)性。

  2. 依賴注入(DI):Spring的核心功能是依賴注入,它將組件之間的依賴關(guān)系轉(zhuǎn)移給容器來(lái)管理。這種松耦合的設(shè)計(jì)使得代碼更靈活、可測(cè)試性更強(qiáng),并降低了代碼的耦合度。

  3. 面向接口編程:Spring鼓勵(lì)使用面向接口的編程風(fēng)格,通過(guò)接口定義了各種組件之間的契約,使得代碼更易于擴(kuò)展和修改,并提供了解耦的效果。

  4. 組件化開(kāi)發(fā):Spring鼓勵(lì)使用組件化開(kāi)發(fā)的思想,將應(yīng)用程序拆分為功能模塊化的組件,每個(gè)組件負(fù)責(zé)特定的功能。這種模塊化的設(shè)計(jì)使得應(yīng)用程序更容易理解、擴(kuò)展和維護(hù)。

  5. 輕量級(jí)和可擴(kuò)展性:Spring框架本身非常輕量級(jí),不需要很大的資源開(kāi)銷。同時(shí),Spring提供了許多可選的模塊和擴(kuò)展,可以根據(jù)需求進(jìn)行選擇和集成,實(shí)現(xiàn)高度可定制的應(yīng)用程序開(kāi)發(fā)。

  6. 寬松的集成:Spring集成了許多其他流行的開(kāi)源框架和技術(shù),例如Hibernate、JPA、MyBatis、Spring MVC、Spring Boot等。這種寬松的集成能力使得開(kāi)發(fā)人員可以根據(jù)自己的需求選擇不同的技術(shù)和工具。

  7. 安全性:Spring提供了一套全面的安全性功能,包括身份認(rèn)證、訪問(wèn)控制和加密等。這些功能可以幫助開(kāi)發(fā)人員構(gòu)建安全可靠的應(yīng)用程序。

總的來(lái)說(shuō),Spring框架的優(yōu)勢(shì)在于提供了一種靈活、模塊化、可擴(kuò)展和高度定制的方式來(lái)開(kāi)發(fā)企業(yè)級(jí)應(yīng)用程序。它促進(jìn)了良好的設(shè)計(jì)原則和最佳實(shí)踐,提高了開(kāi)發(fā)效率和代碼質(zhì)量。同時(shí),Spring擁有龐大的社區(qū)支持和廣泛的文檔資源,使開(kāi)發(fā)人員能夠輕松學(xué)習(xí)和解決問(wèn)題。

Spring是如何簡(jiǎn)化開(kāi)發(fā)的?

Spring框架通過(guò)依賴注入、面向切面編程、組件化開(kāi)發(fā)、技術(shù)整合和豐富的功能模塊,簡(jiǎn)化了企業(yè)級(jí)應(yīng)用程序的開(kāi)發(fā)過(guò)程。它提供了一種靈活、模塊化、可擴(kuò)展和高度定制的方式來(lái)開(kāi)發(fā)應(yīng)用程序,提高了開(kāi)發(fā)效率和代碼質(zhì)量。

IOC 運(yùn)行時(shí)序

當(dāng)調(diào)用 ApplicationContext 的 refresh() 方法時(shí),Spring 容器將執(zhí)行以下一系列步驟以完成初始化過(guò)程:

原文鏈接:【死磕 Spring】----- 深入分析 ApplicationContext 的 refresh()_為什么applicationcontext1.refresh();-CSDN博客

當(dāng)調(diào)用 ApplicationContext 的 refresh() 方法時(shí),Spring 容器將執(zhí)行以下一系列步驟以完成初始化過(guò)程:

@Override
public void refresh() throws BeansException, IllegalStateException {synchronized (this.startupShutdownMonitor) {// 準(zhǔn)備刷新上下文環(huán)境prepareRefresh();
?// 創(chuàng)建并初始化 BeanFactoryConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
?// 填充BeanFactory功能prepareBeanFactory(beanFactory);
?try {// 提供子類覆蓋的額外處理,即子類處理自定義的BeanFactoryPostProcesspostProcessBeanFactory(beanFactory);
?// 激活各種BeanFactory處理器invokeBeanFactoryPostProcessors(beanFactory);
?// 注冊(cè)攔截Bean創(chuàng)建的Bean處理器,即注冊(cè) BeanPostProcessorregisterBeanPostProcessors(beanFactory);
?// 初始化上下文中的資源文件,如國(guó)際化文件的處理等initMessageSource();
?// 初始化上下文事件廣播器initApplicationEventMulticaster();
?// 給子類擴(kuò)展初始化其他BeanonRefresh();
?// 在所有bean中查找listener bean,然后注冊(cè)到廣播器中registerListeners();
?// 初始化剩下的單例Bean(非延遲加載的)finishBeanFactoryInitialization(beanFactory);
?// 完成刷新過(guò)程,通知生命周期處理器lifecycleProcessor刷新過(guò)程,同時(shí)發(fā)出ContextRefreshEvent通知?jiǎng)e人finishRefresh();}
?catch (BeansException ex) {if (logger.isWarnEnabled()) {logger.warn("Exception encountered during context initialization - " +"cancelling refresh attempt: " + ex);}
?//  銷毀已經(jīng)創(chuàng)建的BeandestroyBeans();
?// 重置容器激活標(biāo)簽cancelRefresh(ex);
?// 拋出異常throw ex;}
?finally {// Reset common introspection caches in Spring's core, since we// might not ever need metadata for singleton beans anymore...resetCommonCaches();}}
}

prepareRefresh()??初始化上下文環(huán)境

初始化上下文環(huán)境,對(duì)系統(tǒng)的環(huán)境變量或者系統(tǒng)屬性進(jìn)行準(zhǔn)備和校驗(yàn),如環(huán)境變量中必須設(shè)置某個(gè)值才能運(yùn)行,否則不能運(yùn)行,這個(gè)時(shí)候可以在這里加這個(gè)校驗(yàn),重寫(xiě)initPropertySources方法就好了

該方法主要是做一些準(zhǔn)備工作,如:

  1. 設(shè)置 context 啟動(dòng)時(shí)間

  2. 設(shè)置 context 的當(dāng)前狀態(tài)

  3. 初始化 context environment 中占位符

  4. 對(duì)屬性進(jìn)行必要的驗(yàn)證

obtainFreshBeanFactory()? ?創(chuàng)建并初始化 BeanFactory

創(chuàng)建并初始化 BeanFactory

核心方法就在 refreshBeanFactory() ,該方法的核心任務(wù)就是創(chuàng)建 BeanFactory 并對(duì)其就行一番初始化。如下:

protected final void refreshBeanFactory() throws BeansException {if (hasBeanFactory()) {destroyBeans();closeBeanFactory();}try {DefaultListableBeanFactory beanFactory = createBeanFactory();beanFactory.setSerializationId(getId());customizeBeanFactory(beanFactory);loadBeanDefinitions(beanFactory);synchronized (this.beanFactoryMonitor) {this.beanFactory = beanFactory;}}catch (IOException ex) {throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex);}
}

判斷當(dāng)前容器是否存在一個(gè) BeanFactory,如果存在則對(duì)其進(jìn)行銷毀和關(guān)閉 調(diào)用 createBeanFactory() 創(chuàng)建一個(gè) BeanFactory 實(shí)例,其實(shí)就是 DefaultListableBeanFactory 自定義 BeanFactory 加載 BeanDefinition loadBeanDefinitions() 是定義在 BeanDefinitionReader

將創(chuàng)建好的 bean 工廠的引用交給的 context 來(lái)管理

prepareBeanFactory(beanFactory)??填充 BeanFactory 功能

上面獲取獲取的 BeanFactory 除了加載了一些 BeanDefinition 就沒(méi)有其他任何東西了,這個(gè)時(shí)候其實(shí)還不能投入生產(chǎn),因?yàn)檫€少配置了一些東西,比如 context的 ClassLoader 和 后置處理器等等。

protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) {// 設(shè)置beanFactory的classLoaderbeanFactory.setBeanClassLoader(getClassLoader());// 設(shè)置beanFactory的表達(dá)式語(yǔ)言處理器,Spring3開(kāi)始增加了對(duì)語(yǔ)言表達(dá)式的支持,默認(rèn)可以使用#{bean.xxx}的形式來(lái)調(diào)用相關(guān)屬性值beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader()));// 為beanFactory增加一個(gè)默認(rèn)的propertyEditorbeanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment()));// 添加ApplicationContextAwareProcessorbeanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));// 設(shè)置忽略自動(dòng)裝配的接口beanFactory.ignoreDependencyInterface(EnvironmentAware.class);beanFactory.ignoreDependencyInterface(EmbeddedValueResolverAware.class);beanFactory.ignoreDependencyInterface(ResourceLoaderAware.class);beanFactory.ignoreDependencyInterface(ApplicationEventPublisherAware.class);beanFactory.ignoreDependencyInterface(MessageSourceAware.class);beanFactory.ignoreDependencyInterface(ApplicationContextAware.class);// 設(shè)置幾個(gè)自動(dòng)裝配的特殊規(guī)則beanFactory.registerResolvableDependency(BeanFactory.class, beanFactory);beanFactory.registerResolvableDependency(ResourceLoader.class, this);beanFactory.registerResolvableDependency(ApplicationEventPublisher.class, this);beanFactory.registerResolvableDependency(ApplicationContext.class, this);// Register early post-processor for detecting inner beans as ApplicationListeners.beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(this));// 增加對(duì)AspectJ的支持if (beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));// Set a temporary ClassLoader for type matching.beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));}// 注冊(cè)默認(rèn)的系統(tǒng)環(huán)境beanif (!beanFactory.containsLocalBean(ENVIRONMENT_BEAN_NAME)) {beanFactory.registerSingleton(ENVIRONMENT_BEAN_NAME, getEnvironment());}if (!beanFactory.containsLocalBean(SYSTEM_PROPERTIES_BEAN_NAME)) {beanFactory.registerSingleton(SYSTEM_PROPERTIES_BEAN_NAME, getEnvironment().getSystemProperties());}if (!beanFactory.containsLocalBean(SYSTEM_ENVIRONMENT_BEAN_NAME)) {beanFactory.registerSingleton(SYSTEM_ENVIRONMENT_BEAN_NAME, getEnvironment().getSystemEnvironment());}

postProcessBeanFactory()??提供子類覆蓋的額外處理

提供子類覆蓋的額外處理,即子類處理自定義的BeanFactoryPostProcess

protected void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {beanFactory.addBeanPostProcessor(new ServletContextAwareProcessor(this.servletContext, this.servletConfig));beanFactory.ignoreDependencyInterface(ServletContextAware.class);beanFactory.ignoreDependencyInterface(ServletConfigAware.class);
?WebApplicationContextUtils.registerWebApplicationScopes(beanFactory, this.servletContext);WebApplicationContextUtils.registerEnvironmentBeans(beanFactory, this.servletContext, this.servletConfig);
}

添加 ServletContextAwareProcessor 到 BeanFactory 容器中,該 processor 實(shí)現(xiàn) BeanPostProcessor 接口,主要用于將ServletContext 傳遞給實(shí)現(xiàn)了 ServletContextAware 接口的 bean 忽略 ServletContextAware、ServletConfigAware 注冊(cè) WEB 應(yīng)用特定的域(scope)到 beanFactory 中,以便 WebApplicationContext 可以使用它們。比如 “request” , “session” , “globalSession” , “application” 注冊(cè) WEB 應(yīng)用特定的 Environment bean 到 beanFactory 中,以便WebApplicationContext 可以使用它們。如:“contextParameters”, “contextAttributes”

invokeBeanFactoryPostProcessors()? ? 激活各種BeanFactory處理器

public static void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory, List<BeanFactoryPostProcessor> beanFactoryPostProcessors) {
?// 定義一個(gè) set 保存所有的 BeanFactoryPostProcessorsSet<String> processedBeans = new HashSet<>();
?// 如果當(dāng)前 BeanFactory 為 BeanDefinitionRegistryif (beanFactory instanceof BeanDefinitionRegistry) {BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory;// BeanFactoryPostProcessor 集合List<BeanFactoryPostProcessor> regularPostProcessors = new ArrayList<>();// BeanDefinitionRegistryPostProcessor 集合List<BeanDefinitionRegistryPostProcessor> registryProcessors = new ArrayList<>();
?// 迭代注冊(cè)的 beanFactoryPostProcessorsfor (BeanFactoryPostProcessor postProcessor : beanFactoryPostProcessors) {// 如果是 BeanDefinitionRegistryPostProcessor,則調(diào)用 postProcessBeanDefinitionRegistry 進(jìn)行注冊(cè),// 同時(shí)加入到 registryProcessors 集合中if (postProcessor instanceof BeanDefinitionRegistryPostProcessor) {BeanDefinitionRegistryPostProcessor registryProcessor =(BeanDefinitionRegistryPostProcessor) postProcessor;registryProcessor.postProcessBeanDefinitionRegistry(registry);registryProcessors.add(registryProcessor);}else {// 否則當(dāng)做普通的 BeanFactoryPostProcessor 處理// 添加到 regularPostProcessors 集合中即可,便于后面做后續(xù)處理regularPostProcessors.add(postProcessor);}}
?// 用于保存當(dāng)前處理的 BeanDefinitionRegistryPostProcessorList<BeanDefinitionRegistryPostProcessor> currentRegistryProcessors = new ArrayList<>();
?// 首先處理實(shí)現(xiàn)了 PriorityOrdered (有限排序接口)的 BeanDefinitionRegistryPostProcessorString[] postProcessorNames =beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);for (String ppName : postProcessorNames) {if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));processedBeans.add(ppName);}}
?// 排序sortPostProcessors(currentRegistryProcessors, beanFactory);
?// 加入registryProcessors集合registryProcessors.addAll(currentRegistryProcessors);
?// 調(diào)用所有實(shí)現(xiàn)了 PriorityOrdered 的 BeanDefinitionRegistryPostProcessors 的 postProcessBeanDefinitionRegistry()invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
?// 清空,以備下次使用currentRegistryProcessors.clear();
?// 其次,調(diào)用是實(shí)現(xiàn)了 Ordered(普通排序接口)的 BeanDefinitionRegistryPostProcessors// 邏輯和 上面一樣postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);for (String ppName : postProcessorNames) {if (!processedBeans.contains(ppName) && beanFactory.isTypeMatch(ppName, Ordered.class)) {currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));processedBeans.add(ppName);}}sortPostProcessors(currentRegistryProcessors, beanFactory);registryProcessors.addAll(currentRegistryProcessors);invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);currentRegistryProcessors.clear();
?// 最后調(diào)用其他的 BeanDefinitionRegistryPostProcessorsboolean reiterate = true;while (reiterate) {reiterate = false;// 獲取 BeanDefinitionRegistryPostProcessorpostProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);for (String ppName : postProcessorNames) {
?// 沒(méi)有包含在 processedBeans 中的(因?yàn)榘说亩家呀?jīng)處理了)if (!processedBeans.contains(ppName)) {currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));processedBeans.add(ppName);reiterate = true;}}
?// 與上面處理邏輯一致sortPostProcessors(currentRegistryProcessors, beanFactory);registryProcessors.addAll(currentRegistryProcessors);invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);currentRegistryProcessors.clear();}
?// 調(diào)用所有 BeanDefinitionRegistryPostProcessor (包括手動(dòng)注冊(cè)和通過(guò)配置文件注冊(cè))// 和 BeanFactoryPostProcessor(只有手動(dòng)注冊(cè))的回調(diào)函數(shù)(postProcessBeanFactory())invokeBeanFactoryPostProcessors(registryProcessors, beanFactory);invokeBeanFactoryPostProcessors(regularPostProcessors, beanFactory);}
?else {// 如果不是 BeanDefinitionRegistry 只需要調(diào)用其回調(diào)函數(shù)(postProcessBeanFactory())即可invokeBeanFactoryPostProcessors(beanFactoryPostProcessors, beanFactory);}
?//String[] postProcessorNames =beanFactory.getBeanNamesForType(BeanFactoryPostProcessor.class, true, false);
?// 這里同樣需要區(qū)分 PriorityOrdered 、Ordered 和 no OrderedList<BeanFactoryPostProcessor> priorityOrderedPostProcessors = new ArrayList<>();List<String> orderedPostProcessorNames = new ArrayList<>();List<String> nonOrderedPostProcessorNames = new ArrayList<>();for (String ppName : postProcessorNames) {// 已經(jīng)處理過(guò)了的,跳過(guò)if (processedBeans.contains(ppName)) {// skip - already processed in first phase above}// PriorityOrderedelse if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {priorityOrderedPostProcessors.add(beanFactory.getBean(ppName, BeanFactoryPostProcessor.class));}// Orderedelse if (beanFactory.isTypeMatch(ppName, Ordered.class)) {orderedPostProcessorNames.add(ppName);}// no Orderedelse {nonOrderedPostProcessorNames.add(ppName);}}
?// First, PriorityOrdered 接口sortPostProcessors(priorityOrderedPostProcessors, beanFactory);invokeBeanFactoryPostProcessors(priorityOrderedPostProcessors, beanFactory);
?// Next, Ordered 接口List<BeanFactoryPostProcessor> orderedPostProcessors = new ArrayList<>();for (String postProcessorName : orderedPostProcessorNames) {orderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));}sortPostProcessors(orderedPostProcessors, beanFactory);invokeBeanFactoryPostProcessors(orderedPostProcessors, beanFactory);
?// Finally, no orderedList<BeanFactoryPostProcessor> nonOrderedPostProcessors = new ArrayList<>();for (String postProcessorName : nonOrderedPostProcessorNames) {nonOrderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));}invokeBeanFactoryPostProcessors(nonOrderedPostProcessors, beanFactory);
?// Clear cached merged bean definitions since the post-processors might have// modified the original metadata, e.g. replacing placeholders in values...beanFactory.clearMetadataCache();
}

上述代碼較長(zhǎng),但是處理邏輯較為單一,就是對(duì)所有的 BeanDefinitionRegistryPostProcessors 、手動(dòng)注冊(cè)的 BeanFactoryPostProcessor 以及通過(guò)配置文件方式的 BeanFactoryPostProcessor 按照 PriorityOrdered 、 Ordered、no ordered 三種方式分開(kāi)處理、調(diào)用。

registerBeanPostProcessors

注冊(cè)攔截Bean創(chuàng)建的Bean處理器,即注冊(cè) BeanPostProcessor

與 BeanFactoryPostProcessor 一樣,也是委托給 PostProcessorRegistrationDelegate 來(lái)實(shí)現(xiàn)的。

public static void registerBeanPostProcessors(ConfigurableListableBeanFactory beanFactory, AbstractApplicationContext applicationContext) {
?// 所有的 BeanPostProcessorsString[] postProcessorNames = beanFactory.getBeanNamesForType(BeanPostProcessor.class, true, false);
?// 注冊(cè) BeanPostProcessorChecker// 主要用于記錄一些 bean 的信息,這些 bean 不符合所有 BeanPostProcessors 處理的資格時(shí)int beanProcessorTargetCount = beanFactory.getBeanPostProcessorCount() + 1 + postProcessorNames.length;beanFactory.addBeanPostProcessor(new BeanPostProcessorChecker(beanFactory, beanProcessorTargetCount));
?// 區(qū)分 PriorityOrdered、Ordered 、 no orderedList<BeanPostProcessor> priorityOrderedPostProcessors = new ArrayList<>();List<String> orderedPostProcessorNames = new ArrayList<>();List<String> nonOrderedPostProcessorNames = new ArrayList<>();// MergedBeanDefinitionList<BeanPostProcessor> internalPostProcessors = new ArrayList<>();for (String ppName : postProcessorNames) {if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);priorityOrderedPostProcessors.add(pp);if (pp instanceof MergedBeanDefinitionPostProcessor) {internalPostProcessors.add(pp);}}else if (beanFactory.isTypeMatch(ppName, Ordered.class)) {orderedPostProcessorNames.add(ppName);}else {nonOrderedPostProcessorNames.add(ppName);}}
?// First, PriorityOrderedsortPostProcessors(priorityOrderedPostProcessors, beanFactory);registerBeanPostProcessors(beanFactory, priorityOrderedPostProcessors);
?// Next, OrderedList<BeanPostProcessor> orderedPostProcessors = new ArrayList<>();for (String ppName : orderedPostProcessorNames) {BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);orderedPostProcessors.add(pp);if (pp instanceof MergedBeanDefinitionPostProcessor) {internalPostProcessors.add(pp);}}sortPostProcessors(orderedPostProcessors, beanFactory);registerBeanPostProcessors(beanFactory, orderedPostProcessors);
?// onOrderedList<BeanPostProcessor> nonOrderedPostProcessors = new ArrayList<>();for (String ppName : nonOrderedPostProcessorNames) {BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);nonOrderedPostProcessors.add(pp);if (pp instanceof MergedBeanDefinitionPostProcessor) {internalPostProcessors.add(pp);}}registerBeanPostProcessors(beanFactory, nonOrderedPostProcessors);
?// Finally, all internal BeanPostProcessors.sortPostProcessors(internalPostProcessors, beanFactory);registerBeanPostProcessors(beanFactory, internalPostProcessors);
?// 重新注冊(cè)用來(lái)自動(dòng)探測(cè)內(nèi)部ApplicationListener的post-processor,這樣可以將他們移到處理器鏈條的末尾beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(applicationContext));
}

initMessageSource

初始化上下文中的資源文件,如國(guó)際化文件的處理等

initApplicationEventMulticaster

初始化上下文事件廣播器

onRefresh

給子類擴(kuò)展初始化其他Bean

預(yù)留給 AbstractApplicationContext 的子類用于初始化其他特殊的 bean,該方法需要在所有單例 bean 初始化之前調(diào)用。

registerListeners

在所有 bean 中查找 listener bean,然后注冊(cè)到廣播器中

protected void registerListeners() {// 注冊(cè)靜態(tài) 監(jiān)聽(tīng)器for (ApplicationListener<?> listener : getApplicationListeners()) {getApplicationEventMulticaster().addApplicationListener(listener);}
?String[] listenerBeanNames = getBeanNamesForType(ApplicationListener.class, true, false);for (String listenerBeanName : listenerBeanNames) {getApplicationEventMulticaster().addApplicationListenerBean(listenerBeanName);}
?// 至此,已經(jīng)完成將監(jiān)聽(tīng)器注冊(cè)到ApplicationEventMulticaster中,下面將發(fā)布前期的事件給監(jiān)聽(tīng)器。Set<ApplicationEvent> earlyEventsToProcess = this.earlyApplicationEvents;this.earlyApplicationEvents = null;if (earlyEventsToProcess != null) {for (ApplicationEvent earlyEvent : earlyEventsToProcess) {getApplicationEventMulticaster().multicastEvent(earlyEvent);}}
}

finishBeanFactoryInitialization

初始化剩下的單例Bean(非延遲加載的)

protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {// 初始化轉(zhuǎn)換器if (beanFactory.containsBean(CONVERSION_SERVICE_BEAN_NAME) &&beanFactory.isTypeMatch(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class)) {beanFactory.setConversionService(beanFactory.getBean(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class));}
?// 如果之前沒(méi)有注冊(cè) bean 后置處理器(例如PropertyPlaceholderConfigurer),則注冊(cè)默認(rèn)的解析器if (!beanFactory.hasEmbeddedValueResolver()) {beanFactory.addEmbeddedValueResolver(strVal -> getEnvironment().resolvePlaceholders(strVal));}
?// 初始化 Initialize LoadTimeWeaverAware beans early to allow for registering their transformers early.String[] weaverAwareNames = beanFactory.getBeanNamesForType(LoadTimeWeaverAware.class, false, false);for (String weaverAwareName : weaverAwareNames) {getBean(weaverAwareName);}
?// 停止使用臨時(shí)的 ClassLoaderbeanFactory.setTempClassLoader(null);
?//beanFactory.freezeConfiguration();
?// 初始化所有剩余的單例(非延遲初始化)beanFactory.preInstantiateSingletons();
}

finishRefresh

完成刷新過(guò)程,通知生命周期處理器 lifecycleProcessor 刷新過(guò)程,同時(shí)發(fā)出 ContextRefreshEvent 通知?jiǎng)e人

主要是調(diào)用 LifecycleProcessor#onRefresh() ,并且發(fā)布事件(ContextRefreshedEvent)。

protected void finishRefresh() {// Clear context-level resource caches (such as ASM metadata from scanning).clearResourceCaches();
?// Initialize lifecycle processor for this context.initLifecycleProcessor();
?// Propagate refresh to lifecycle processor first.getLifecycleProcessor().onRefresh();
?// Publish the final event.publishEvent(new ContextRefreshedEvent(this));
?// Participate in LiveBeansView MBean, if active.LiveBeansView.registerApplicationContext(this);
}

Spring的AOP的底層實(shí)現(xiàn)原理

bean的創(chuàng)建過(guò)程中有一個(gè)步驟可以對(duì)bean進(jìn)行擴(kuò)展實(shí)現(xiàn),aop本身就是一個(gè)擴(kuò)展功能,所以在BeanPostProcessor的后置處理方法中來(lái)進(jìn)行實(shí)現(xiàn)

不論使用哪種方式,Spring AOP的實(shí)現(xiàn)過(guò)程都包括以下幾個(gè)關(guān)鍵步驟:

  1. 定義切點(diǎn)(Pointcut):切點(diǎn)定義了在何處應(yīng)用切面邏輯的具體位置。通過(guò)表達(dá)式或注解等方式,確定應(yīng)該被代理的目標(biāo)方法或目標(biāo)類。

  2. 編寫(xiě)切面(Aspect):切面是具體的橫切邏輯實(shí)現(xiàn),包括在目標(biāo)方法執(zhí)行前后執(zhí)行的操作(通知,Advices)。切面可以包括一個(gè)或多個(gè)通知的定義。

  3. 創(chuàng)建代理對(duì)象:Spring根據(jù)切點(diǎn)和切面信息,生成動(dòng)態(tài)代理或字節(jié)碼增強(qiáng)的代理對(duì)象。代理對(duì)象在執(zhí)行目標(biāo)方法時(shí),會(huì)根據(jù)切點(diǎn)和切面定義,執(zhí)行相應(yīng)的切面邏輯。

總結(jié)來(lái)說(shuō),Spring AOP的底層實(shí)現(xiàn)原理是通過(guò)動(dòng)態(tài)代理或字節(jié)碼生成,將切面邏輯織入到目標(biāo)對(duì)象或目標(biāo)類中,實(shí)現(xiàn)橫切關(guān)注點(diǎn)的解耦和重用。

3.在執(zhí)行方法調(diào)用的時(shí)候,會(huì)調(diào)用到生成的字節(jié)碼文件中,直接回找到DynamicAdvisoredInterceptor類中的intercept方法,從此方法開(kāi)始執(zhí)行

4.根據(jù)之前定義好的通知來(lái)生成攔截器

5.從攔截器鏈中依次獲取每一個(gè)通知開(kāi)始進(jìn)行執(zhí)行,在執(zhí)行過(guò)程中,為了方便找到下一個(gè)通知是哪個(gè),會(huì)有一個(gè)CglibMethodInvocation的對(duì)象,找的時(shí)候是從-1的位置依次開(kāi)始查找并且執(zhí)行的。

說(shuō)說(shuō)你對(duì)Aop的理解?

AOP全稱叫做 Aspect Oriented Programming 面向切面編程。它是為解耦而生的,解耦是程序員編碼開(kāi)發(fā)過(guò)程中一直追求的境界,AOP在業(yè)務(wù)類的隔離上,絕對(duì)是做到了解耦,在這里面有幾個(gè)核心的概念:

  • 切面(Aspect): 指關(guān)注點(diǎn)模塊化,這個(gè)關(guān)注點(diǎn)可能會(huì)橫切多個(gè)對(duì)象。事務(wù)管理是企業(yè)級(jí)Java應(yīng)用中有關(guān)橫切關(guān)注點(diǎn)的例子。 在Spring AOP中,切面可以使用通用類基于模式的方式(schema-based approach)或者在普通類中以@Aspect注解(@AspectJ 注解方式)來(lái)實(shí)現(xiàn)。(Aspect作為一個(gè)模塊來(lái)組織Join point , PointCut來(lái)篩選要執(zhí)行的連接點(diǎn),Advice在切面的某個(gè)特定的連接點(diǎn)上執(zhí)行的動(dòng)作),(一個(gè)Aspect對(duì)應(yīng)多個(gè)join point,一個(gè)joinPoint 有多個(gè) advice)

  • 連接點(diǎn)(Join point): 在程序執(zhí)行過(guò)程中某個(gè)特定的點(diǎn),例如某個(gè)方法調(diào)用的時(shí)間點(diǎn)或者處理異常的時(shí)間點(diǎn)。在Spring AOP中,一個(gè)連接點(diǎn)總是代表一個(gè)方法的執(zhí)行。

  • 通知(Advice): 在切面的某個(gè)特定的連接點(diǎn)上執(zhí)行的動(dòng)作。通知有多種類型,包括“around”, “before” and “after”等等。通知的類型將在后面的章節(jié)進(jìn)行討論。 許多AOP框架,包括Spring在內(nèi),都是以攔截器做通知模型的,并維護(hù)著一個(gè)以連接點(diǎn)為中心的攔截器鏈。

  • 切點(diǎn)(Pointcut): 匹配連接點(diǎn)的斷言。通知和切點(diǎn)表達(dá)式相關(guān)聯(lián),并在滿足這個(gè)切點(diǎn)的連接點(diǎn)上運(yùn)行(例如,當(dāng)執(zhí)行某個(gè)特定名稱的方法時(shí))。切點(diǎn)表達(dá)式如何和連接點(diǎn)匹配是AOP的核心:Spring默認(rèn)使用AspectJ切點(diǎn)語(yǔ)義。

  • 引入(Introduction): 聲明額外的方法或者某個(gè)類型的字段。Spring允許引入新的接口(以及一個(gè)對(duì)應(yīng)的實(shí)現(xiàn))到任何被通知的對(duì)象上。例如,可以使用引入來(lái)使bean實(shí)現(xiàn) IsModified接口, 以便簡(jiǎn)化緩存機(jī)制(在AspectJ社區(qū),引入也被稱為內(nèi)部類型聲明(inter))。

  • 目標(biāo)對(duì)象(Target object): 被一個(gè)或者多個(gè)切面所通知的對(duì)象。也被稱作被通知(advised)對(duì)象。既然Spring AOP是通過(guò)運(yùn)行時(shí)代理實(shí)現(xiàn)的,那么這個(gè)對(duì)象永遠(yuǎn)是一個(gè)被代理(proxied)的對(duì)象。

  • AOP代理(AOP proxy):AOP框架創(chuàng)建的對(duì)象,用來(lái)實(shí)現(xiàn)切面契約(aspect contract)(包括通知方法執(zhí)行等功能)。在Spring中,AOP代理可以是JDK動(dòng)態(tài)代理或CGLIB代理。

  • 織入(Weaving): 把切面連接到其它的應(yīng)用程序類型或者對(duì)象上,并創(chuàng)建一個(gè)被被通知的對(duì)象的過(guò)程。這個(gè)過(guò)程可以在編譯時(shí)(例如使用AspectJ編譯器)、類加載時(shí)或運(yùn)行時(shí)中完成。 Spring和其他純Java AOP框架一樣,是在運(yùn)行時(shí)完成織入的。

    這些概念都太學(xué)術(shù)了,如果更簡(jiǎn)單的解釋呢,其實(shí)非常簡(jiǎn)單:

    任何一個(gè)系統(tǒng)都是由不同的組件組成的,每個(gè)組件負(fù)責(zé)一塊特定的功能,當(dāng)然會(huì)存在很多組件是跟業(yè)務(wù)無(wú)關(guān)的,例如日志、事務(wù)、權(quán)限等核心服務(wù)組件,這些核心服務(wù)組件經(jīng)常融入到具體的業(yè)務(wù)邏輯中,如果我們?yōu)槊恳粋€(gè)具體業(yè)務(wù)邏輯操作都添加這樣的代碼,很明顯代碼冗余太多,因此我們需要將這些公共的代碼邏輯抽象出來(lái)變成一個(gè)切面,然后注入到目標(biāo)對(duì)象(具體業(yè)務(wù))中去,AOP正是基于這樣的一個(gè)思路實(shí)現(xiàn)的,通過(guò)動(dòng)態(tài)代理的方式,將需要注入切面的對(duì)象進(jìn)行代理,在進(jìn)行調(diào)用的時(shí)候,將公共的邏輯直接添加進(jìn)去,而不需要修改原有業(yè)務(wù)的邏輯代碼,只需要在原來(lái)的業(yè)務(wù)邏輯基礎(chǔ)之上做一些增強(qiáng)功能即可。

說(shuō)說(shuō)你對(duì)IOC的理解?

在 Spring 中,IoC 是 Inversion of Control(控制反轉(zhuǎn))的縮寫(xiě),是 Spring 框架的一個(gè)重要特性。IoC 的本質(zhì)是將對(duì)對(duì)象的控制權(quán)從應(yīng)用程序本身轉(zhuǎn)移到了框架或容器中,由容器來(lái)負(fù)責(zé)對(duì)象的創(chuàng)建、管理和注入依賴對(duì)象,從而降低了組件之間的耦合度,提高了代碼的可重用性和可測(cè)試性。在 Spring 中,IoC 容器負(fù)責(zé)管理應(yīng)用程序中的對(duì)象及其之間的依賴關(guān)系,開(kāi)發(fā)人員不再需要手動(dòng)創(chuàng)建對(duì)象和管理對(duì)象之間的關(guān)聯(lián)關(guān)系,而是通過(guò)配置文件或注解告訴容器如何創(chuàng)建和組裝對(duì)象。IoC 容器負(fù)責(zé)實(shí)例化對(duì)象、注入依賴、生命周期管理等工作,開(kāi)發(fā)人員只需要關(guān)注業(yè)務(wù)邏輯的實(shí)現(xiàn),將對(duì)象的創(chuàng)建和依賴關(guān)系的管理交由容器來(lái)完成。在 Spring 中,IoC 容器主要有兩種實(shí)現(xiàn)方式:BeanFactory 和 ApplicationContext。1. **BeanFactory:** 是 Spring 框架的基礎(chǔ)容器,提供了基本的 IoC 功能,可以延遲加載(Lazy Loading)和按需注入(On-demand Injection)Bean,適合在資源有限的環(huán)境下使用。2. **ApplicationContext:** 是 BeanFactory 的擴(kuò)展,提供了更多的企業(yè)級(jí)功能和特性,如國(guó)際化支持、事件傳播、AOP、聲明式事務(wù)管理等,適合大多數(shù)企業(yè)級(jí)應(yīng)用程序使用。通過(guò) IoC 容器,Spring 管理了應(yīng)用程序中的所有對(duì)象,并負(fù)責(zé)解決對(duì)象之間的依賴關(guān)系,從而實(shí)現(xiàn)了代碼的松耦合、易于維護(hù)和測(cè)試的優(yōu)勢(shì)。開(kāi)發(fā)人員可以通過(guò)配置文件或注解,實(shí)現(xiàn)對(duì)象之間的依賴注入,讓 IoC 容器來(lái)負(fù)責(zé)對(duì)象創(chuàng)建和管理,提高了應(yīng)用程序的靈活性和可擴(kuò)展性。

依賴注入DI 的概念

DI 是 Dependency Injection(依賴注入)的縮寫(xiě),它是面向?qū)ο缶幊讨械囊环N設(shè)計(jì)模式,在 Spring 框架中被廣泛應(yīng)用。DI 是 IoC(控制反轉(zhuǎn))的一種實(shí)現(xiàn)方式,通過(guò)依賴注入的方式來(lái)實(shí)現(xiàn)對(duì)象之間的解耦和管理依賴關(guān)系。

在 DI 中,對(duì)象不再負(fù)責(zé)創(chuàng)建或查找依賴的對(duì)象,而是將依賴關(guān)系注入到對(duì)象之中。這樣做的好處是提高了代碼的可維護(hù)性、可測(cè)試性和可擴(kuò)展性,降低了對(duì)象之間的耦合度,使得代碼更加靈活和易于重用。

在 Spring 框架中,依賴注入可以通過(guò)構(gòu)造函數(shù)注入、Setter 方法注入或字段注入等方式實(shí)現(xiàn)。開(kāi)發(fā)人員可以通過(guò)配置文件(如 XML 配置文件)或注解來(lái)指定依賴關(guān)系,讓 Spring IoC 容器來(lái)實(shí)現(xiàn)依賴注入的過(guò)程。

依賴注入的三種主要類型包括:

1. **構(gòu)造函數(shù)注入(Constructor Injection):** 通過(guò)在構(gòu)造函數(shù)中注入依賴對(duì)象來(lái)實(shí)現(xiàn)依賴注入。

2. **Setter 方法注入(Setter Injection):** 通過(guò) Setter 方法來(lái)設(shè)置依賴對(duì)象,實(shí)現(xiàn)依賴注入。

3. **字段注入(Field Injection):** 通過(guò)字段(屬性)注入的方式來(lái)注入依賴對(duì)象。

依賴注入能夠讓開(kāi)發(fā)人員專注于業(yè)務(wù)邏輯的實(shí)現(xiàn),而不必?fù)?dān)心對(duì)象之間的依賴關(guān)系,提高了代碼的可維護(hù)性和可測(cè)試性。通過(guò) DI,Spring 框架實(shí)現(xiàn)了 IoC 容器的依賴管理功能,讓開(kāi)發(fā)人員將對(duì)象之間的關(guān)系交給容器管理,實(shí)現(xiàn)了控制反轉(zhuǎn)的思想。

談一下spring IOC的底層實(shí)現(xiàn)

底層實(shí)現(xiàn):工作原理,過(guò)程,數(shù)據(jù)結(jié)構(gòu),流程,設(shè)計(jì)模式,設(shè)計(jì)思想

你對(duì)他的理解和你了解過(guò)的實(shí)現(xiàn)過(guò)程

反射,工廠,設(shè)計(jì)模式,關(guān)鍵的幾個(gè)方法

createBeanFactory , getBean ,doGetBean , createBean , doCreateBean,createBeanInstance(getDeclaredConstructor(),newinstance),populateBean

1.先通過(guò)createBeanFactory 創(chuàng)建一個(gè)Bean工廠(DefaultListableBeanFactory)

2.開(kāi)始循環(huán)創(chuàng)建對(duì)象,因?yàn)槿萜髦械腷ean默認(rèn)都是單例的,所以優(yōu)先通過(guò)getBean,doGetBean從容器中查找,找不到的話,

3.通過(guò)createBean,doCreateBean方法,以反射的方式創(chuàng)建對(duì)象,一般情況下使用的是無(wú)參的構(gòu)造器(getDeclaredConstructor(),newinstance)

4.進(jìn)行對(duì)象的屬性填充populateBean

5.進(jìn)行其他的初始化操作(initializingBean)

BeanFactory和ApplicationContext有什么區(qū)別

相同:

  • Spring提供了兩種不同的IOC 容器,一個(gè)是BeanFactory,另外一個(gè)是ApplicationContext,它們都是Java interface,ApplicationContext繼承于BeanFactory(ApplicationContext繼承ListableBeanFactory。

  • 它們都可以用來(lái)配置XML屬性,也支持屬性的自動(dòng)注入。

  • 而ListableBeanFactory繼承BeanFactory),BeanFactory 和 ApplicationContext 都提供了一種方式,使用getBean("bean name")獲取bean。

不同:

BeanFactory和ApplicationContext是Spring框架中的兩個(gè)核心接口,它們具有以下區(qū)別:

  1. 功能:

    • BeanFactory是Spring的最基本的接口,提供了IoC容器的基本功能,即管理和獲取Bean。

    • ApplicationContext是對(duì)BeanFactory的擴(kuò)展,提供了更多的功能,如國(guó)際化支持、事件發(fā)布、資源加載、AOP等。

  2. 預(yù)加載:

    • BeanFactory是延遲加載的,即在調(diào)用getBean()方法時(shí)才會(huì)創(chuàng)建和初始化Bean。

    • ApplicationContext可以通過(guò)配置進(jìn)行預(yù)加載,即在容器啟動(dòng)時(shí)就實(shí)例化和初始化所有的單例Bean。

  3. 配置元數(shù)據(jù)的處理:

    • BeanFactory使用BeanDefinition來(lái)管理和解析配置元數(shù)據(jù),Bean的創(chuàng)建由BeanDefinition中的信息描述。

    • ApplicationContext在BeanFactory的基礎(chǔ)上進(jìn)一步擴(kuò)展了對(duì)配置元數(shù)據(jù)的處理,提供更高級(jí)的功能,如自動(dòng)掃描、注解驅(qū)動(dòng)等。

  4. Spring AOP:

    • BeanFactory需要手動(dòng)將AspectJ代理工廠(AspectJProxyFactory)應(yīng)用于Bean,才能支持Spring AOP。

    • ApplicationContext自動(dòng)為Bean提供代理,支持Spring AOP。

  5. 國(guó)際化支持:

    • ApplicationContext提供了更方便的國(guó)際化(i18n)支持,可以基于ResourceBundle實(shí)現(xiàn)多語(yǔ)言切換。

總的來(lái)說(shuō),BeanFactory是更基礎(chǔ)的接口,提供了最基本的IoC容器功能;而ApplicationContext是BeanFactory的擴(kuò)展,提供了更多的功能和便利性,是在實(shí)際應(yīng)用中更常用的接口。如果需要更完整的功能,如AOP、國(guó)際化、事件發(fā)布等,那么建議使用ApplicationContext。但是,如果對(duì)資源要求較低,且只需要基本的Bean管理功能,可以使用BeanFactory來(lái)獲得更輕量級(jí)的容器。

簡(jiǎn)述spring bean的生命周期?

  1. 實(shí)例化(Instantiation):

    • Bean的實(shí)例化是通過(guò)構(gòu)造函數(shù)或工廠方法創(chuàng)建的。

    • 可以在此階段進(jìn)行一些前置處理,容器會(huì)在初始化Bean之前先調(diào)用BeanPostProcessor的postProcessBeforeInitialization()方法。

  2. 屬性設(shè)置(Population):

    • Spring通過(guò)依賴注入(DI)將Bean的屬性進(jìn)行設(shè)置。

    • 可以在此階段進(jìn)行一些屬性相關(guān)的操作,如使用@Autowired、@Value等注解進(jìn)行屬性注入和賦值。

  3. 初始化(Initialization):

    • 在Bean的所有屬性被設(shè)置完后,可以執(zhí)行自定義的初始化邏輯。

    • 可以通過(guò)實(shí)現(xiàn)InitializingBean接口的afterPropertiesSet方法或使用@PostConstruct注解進(jìn)行初始化操作。

    • 可以在此階段進(jìn)行一些初始化相關(guān)的操作,如連接數(shù)據(jù)庫(kù)、讀取配置文件等。

    • BeanPostProcessor的后置處理:如果在容器中定義了BeanPostProcessor,容器會(huì)在初始化Bean之后調(diào)用BeanPostProcessor的postProcessAfterInitialization()方法。

  4. 使用(In Use):

    • Bean可以在應(yīng)用程序中正常使用,處理業(yè)務(wù)邏輯。

    • Bean會(huì)一直處于使用狀態(tài),直到應(yīng)用程序關(guān)閉或Bean被銷毀。

  5. 銷毀(Destruction):

    • 當(dāng)應(yīng)用程序關(guān)閉或手動(dòng)銷毀Bean時(shí),會(huì)執(zhí)行銷毀階段的邏輯。

    • 可以通過(guò)實(shí)現(xiàn)DisposableBean接口的destroy方法或使用@PreDestroy注解進(jìn)行銷毀操作。

    • 可以在此階段進(jìn)行一些資源釋放、清理工作,如關(guān)閉數(shù)據(jù)庫(kù)連接、釋放文件句柄等。

值得注意的是,對(duì)于單例作用域的Bean,默認(rèn)情況下,Spring容器在啟動(dòng)時(shí)會(huì)將所有單例Bean進(jìn)行實(shí)例化和初始化,并在容器關(guān)閉時(shí)銷毀它們;而對(duì)于原型作用域的Bean,Spring容器僅負(fù)責(zé)實(shí)例化和初始化,不負(fù)責(zé)銷毀,需要由調(diào)用者自行管理。

通過(guò)在Bean上實(shí)現(xiàn)相應(yīng)的接口或使用注解,可以對(duì)Bean的生命周期進(jìn)行自定義操作,從而滿足應(yīng)用程序的需求。

spring支持的bean作用域有哪些?

  1. Singleton(默認(rèn)):

    • 單例作用域,每個(gè)Spring容器只創(chuàng)建一個(gè)實(shí)例。

    • 多個(gè)Bean引用同一個(gè)實(shí)例。

    • 適用于無(wú)狀態(tài)的Bean和共享資源的情況。

  2. Prototype:

    • 原型作用域,每次從容器中獲取Bean時(shí)都會(huì)創(chuàng)建一個(gè)新的實(shí)例。

    • 每個(gè)Bean引用不同的實(shí)例。

    • 適用于有狀態(tài)的Bean和非共享資源的情況。

  3. Request:

    • 請(qǐng)求作用域,每個(gè)HTTP請(qǐng)求都會(huì)創(chuàng)建一個(gè)新的實(shí)例。

    • 每個(gè)請(qǐng)求期間的所有Bean引用同一個(gè)實(shí)例。

    • 適用于Web應(yīng)用程序中需要在每個(gè)請(qǐng)求期間共享數(shù)據(jù)的情況。

  4. Session:

    • 會(huì)話作用域,每個(gè)用戶會(huì)話都會(huì)創(chuàng)建一個(gè)新的實(shí)例。

    • 每個(gè)用戶會(huì)話期間的所有Bean引用同一個(gè)實(shí)例。

    • 適用于Web應(yīng)用程序中需要在每個(gè)用戶會(huì)話期間共享數(shù)據(jù)的情況。

  5. Global session(僅適用于Portlet環(huán)境):

    • 全局會(huì)話作用域,每個(gè)Portlet應(yīng)用程序的全局會(huì)話都會(huì)創(chuàng)建一個(gè)新的實(shí)例。

    • 每個(gè)全局會(huì)話期間的所有Bean引用同一個(gè)實(shí)例。

  6. WebSocket(僅適用于WebSocket環(huán)境):

    • WebSocket作用域,每個(gè)WebSocket會(huì)話都會(huì)創(chuàng)建一個(gè)新的實(shí)例。

    • 每個(gè)WebSocket會(huì)話期間的所有Bean引用同一個(gè)實(shí)例。

可以通過(guò)在Spring的Bean聲明中使用@Scope注解或在XML配置文件中使用<bean>元素的scope屬性來(lái)設(shè)置Bean的作用域。例如:

@Component
@Scope("prototype")
public class MyPrototypeBean {// ...
}

或者在XML配置中:

<bean id="myPrototypeBean" class="com.example.MyPrototypeBean" scope="prototype"/>

根據(jù)應(yīng)用程序的需求,選擇適合的作用域可以更好地控制Bean的生命周期和資源管理。

Spring框架中的單例Bean是線程安全的么?

spring只是一中容器,需要看有沒(méi)有對(duì)bean進(jìn)行多線程處理

Spring中的Bean對(duì)象默認(rèn)是單例的,框架并沒(méi)有對(duì)bean進(jìn)行多線程的封裝處理

如果Bean是有狀態(tài)的

無(wú)狀態(tài)就是不會(huì)存儲(chǔ)數(shù)據(jù),你想一下,我們的controller,service和dao本身并不是線程安全的,只是調(diào)用里面的方法,而且多線程調(diào)用一個(gè)實(shí)例的方法,會(huì)在內(nèi)存中復(fù)制遍歷,這是自己線程的工作內(nèi)存,是最安全的。

因此在進(jìn)行使用的時(shí)候,不要在bean中聲明任何有狀態(tài)的實(shí)例變量或者類變量,如果必須如此,也推薦大家使用ThreadLocal把變量變成線程私有,如果bean的實(shí)例變量或者類變量需要在多個(gè)線程之間共享,那么就只能使用synchronized,lock,cas等這些實(shí)現(xiàn)線程同步的方法了。

spring框架中使用了哪些設(shè)計(jì)模式及應(yīng)用場(chǎng)景

1.工廠模式,在各種BeanFactory以及ApplicationContext創(chuàng)建中都用到了

2.模版模式,在各種BeanFactory以及ApplicationContext實(shí)現(xiàn)中也都用到了

3.代理模式,Spring AOP 利用了 AspectJ AOP實(shí)現(xiàn)的! AspectJ AOP 的底層用了動(dòng)態(tài)代理

4.策略模式,加載資源文件的方式,使用了不同的方法,比如:ClassPathResourece,FileSystemResource,ServletContextResource,UrlResource但他們都有共同的借口Resource;在Aop的實(shí)現(xiàn)中,采用了兩種不同的方式,JDK動(dòng)態(tài)代理和CGLIB代理

5.單例模式,比如在創(chuàng)建bean的時(shí)候。

6.觀察者模式,spring中的ApplicationEvent,ApplicationListener,ApplicationEventPublisher

7.適配器模式,MethodBeforeAdviceAdapter,ThrowsAdviceAdapter,AfterReturningAdapter

8.裝飾者模式,源碼中類型帶Wrapper或者Decorator的都是

spring事務(wù)的實(shí)現(xiàn)方式原理是什么?

在使用Spring框架的時(shí)候,可以有兩種事務(wù)的實(shí)現(xiàn)方式,一種是編程式事務(wù),有用戶自己通過(guò)代碼來(lái)控制事務(wù)的處理邏輯,還有一種是聲明式事務(wù),通過(guò)@Transactional注解來(lái)實(shí)現(xiàn)。

在 Spring 中,事務(wù)的實(shí)現(xiàn)方式主要依賴于兩個(gè)核心概念:事務(wù)管理器(Transaction Manager)和代理模式。

  1. 事務(wù)管理器(Transaction Manager):Spring 提供了多個(gè)事務(wù)管理器的實(shí)現(xiàn),例如 DataSourceTransactionManager、JpaTransactionManager 等。事務(wù)管理器負(fù)責(zé)管理事務(wù)的開(kāi)始、提交、回滾等操作。它與底層的數(shù)據(jù)庫(kù)、ORM 框架或其他事務(wù)資源進(jìn)行交互,確保事務(wù)的正確執(zhí)行。

  2. 代理模式:Spring 使用 AOP(面向切面編程)和代理模式來(lái)實(shí)現(xiàn)事務(wù)。當(dāng)方法被標(biāo)注為事務(wù)性時(shí),Spring 會(huì)動(dòng)態(tài)地生成一個(gè)代理類來(lái)包裝該方法,代理類負(fù)責(zé)增加額外的邏輯,如事務(wù)的管理。

工作原理如下:

  1. 通過(guò)配置事務(wù)管理器,將其與當(dāng)前的數(shù)據(jù)源或其他事務(wù)資源進(jìn)行關(guān)聯(lián)。

  2. 在配置文件或注解中對(duì)需要進(jìn)行事務(wù)管理的方法進(jìn)行標(biāo)注 @Transactional。

  3. 當(dāng)標(biāo)注的方法被調(diào)用時(shí),Spring 會(huì)通過(guò)動(dòng)態(tài)代理機(jī)制生成一個(gè)代理類,并在代理類中添加事務(wù)管理的邏輯。代理類會(huì)攔截方法的調(diào)用,并在方法執(zhí)行前后執(zhí)行事務(wù)的開(kāi)啟、提交或回滾等操作。

  4. 根據(jù)配置的事務(wù)屬性,事務(wù)管理器會(huì)根據(jù)方法的執(zhí)行結(jié)果決定事務(wù)的提交或回滾。

具體的實(shí)現(xiàn)機(jī)制包括:

  • 事務(wù)的劃分:通過(guò)注解或配置方式,標(biāo)識(shí)哪些方法需要進(jìn)行事務(wù)管理。

  • 事務(wù)的邊界控制:Spring 會(huì)在適當(dāng)?shù)臅r(shí)機(jī)開(kāi)始一個(gè)事務(wù)(如方法開(kāi)始時(shí))和結(jié)束一個(gè)事務(wù)(如方法結(jié)束時(shí))。

  • 事務(wù)的隔離級(jí)別與傳播行為控制:通過(guò)設(shè)置事務(wù)的隔離級(jí)別(如讀未提交、讀已提交等)和傳播行為(如支持當(dāng)前事務(wù)、新建事務(wù)等),對(duì)事務(wù)進(jìn)行精確控制。

  • 異常處理與事務(wù)回滾:對(duì)于出現(xiàn)異常的情況,根據(jù)配置的事務(wù)屬性決定是否回滾事務(wù)。如果方法內(nèi)部拋出了受檢查異常,Spring 默認(rèn)會(huì)回滾事務(wù);如果拋出非受檢查異常,則根據(jù)異常類型決定是否回滾。

通過(guò)以上的機(jī)制和流程,Spring 能夠提供基于代理的事務(wù)管理功能,將事務(wù)的管理與具體業(yè)務(wù)邏輯解耦,使得事務(wù)管理更加靈活、方便和可控。

Transaction失效

1、bean對(duì)象沒(méi)有被spring容器管理

2、方法的訪問(wèn)修飾符不是public

3、自身調(diào)用問(wèn)題

4、數(shù)據(jù)源沒(méi)有配置事務(wù)管理器

5、數(shù)據(jù)庫(kù)不支持事務(wù)

6、異常被捕獲

7、異常類型錯(cuò)誤或者配置錯(cuò)誤

spring事務(wù)的隔離級(jí)別有哪些?

spring中的事務(wù)隔離級(jí)別就是數(shù)據(jù)庫(kù)的隔離級(jí)別,有以下幾種:

read uncommitted

read committed

repeatable read

serializable

在進(jìn)行配置的時(shí)候,如果數(shù)據(jù)庫(kù)和spring代碼中的隔離級(jí)別不同,那么以spring的配置為主。

spring的事務(wù)傳播機(jī)制是什么?

Spring的事務(wù)傳播(Transaction Propagation)機(jī)制定義了在多個(gè)事務(wù)方法相互調(diào)用時(shí),事務(wù)是如何傳播和管理的。事務(wù)傳播機(jī)制主要用于控制事務(wù)的邊界和隔離級(jí)別,以保證數(shù)據(jù)的一致性和完整性。

Spring框架定義了以下幾種事務(wù)傳播行為:

1、propagation_required:支持當(dāng)前事務(wù),無(wú)事務(wù),另起新事物
2、propagation_required-new:新建事務(wù),若有舊事務(wù),掛起。
3、propagation_supports:支持當(dāng)前事務(wù),無(wú)事務(wù),以非事務(wù)執(zhí)行
4、propagation_mandatory:以事務(wù)方式執(zhí)行,無(wú)事務(wù),拋異常
5、propagation_not_supported:不支持事務(wù),如有事務(wù),掛起
6、propagation_never:以非事務(wù)執(zhí)行,有事務(wù),拋異常
7、propagation_nested:內(nèi)切事務(wù)

這些事務(wù)傳播行為可以通過(guò)在方法上使用 @Transactional 注解來(lái)指定。例如:

@Transactional(propagation = Propagation.REQUIRED)
public void doSomething() {// 執(zhí)行業(yè)務(wù)邏輯
}

需要注意的是,事務(wù)的傳播行為只在嵌套方法調(diào)用中生效,對(duì)于同一個(gè)類中的不同方法調(diào)用,事務(wù)傳播行為不起作用。在開(kāi)發(fā)過(guò)程中,根據(jù)業(yè)務(wù)需求和實(shí)際情況選擇適合的事務(wù)傳播行為可以有效地保證數(shù)據(jù)的一致性和完整性。

NESTED和REQUIRED_NEW的區(qū)別:

REQUIRED_NEW是新建一個(gè)事務(wù)并且新開(kāi)始的這個(gè)事務(wù)與原有事務(wù)無(wú)關(guān),而NESTED則是當(dāng)前存在事務(wù)時(shí)會(huì)開(kāi)啟一個(gè)嵌套事務(wù),在NESTED情況下,父事務(wù)回滾時(shí),子事務(wù)也會(huì)回滾,而REQUIRED_NEW情況下,原有事務(wù)回滾,不會(huì)影響新開(kāi)啟的事務(wù)

NESTED和REQUIRED的區(qū)別:

REQUIRED情況下,調(diào)用方存在事務(wù)時(shí),則被調(diào)用方和調(diào)用方使用同一個(gè)事務(wù),那么被調(diào)用方出現(xiàn)異常時(shí),由于共用一個(gè)事務(wù),所以無(wú)論是否catch異常,事務(wù)都會(huì)回滾,而在NESTED情況下,被調(diào)用方發(fā)生異常時(shí),調(diào)用方可以catch其異常,這樣只有子事務(wù)回滾,父事務(wù)不會(huì)回滾。

spring事務(wù)什么時(shí)候會(huì)失效?

在Spring框架中,事務(wù)的失效可能由以下情況引起:

  1. 未開(kāi)啟事務(wù):在方法上沒(méi)有使用@Transactional注解或在XML配置中未配置事務(wù)管理器和事務(wù)攔截器時(shí),事務(wù)將不會(huì)開(kāi)啟,即使方法中出現(xiàn)數(shù)據(jù)庫(kù)操作也不會(huì)有事務(wù)支持。

  2. 異常未被捕獲:當(dāng)在事務(wù)范圍內(nèi)的方法拋出未被捕獲的異常時(shí),默認(rèn)情況下事務(wù)將回滾。但是,如果異常被捕獲并處理(例如通過(guò)try-catch塊),那么事務(wù)將不會(huì)回滾。

  3. 不受事務(wù)管理的方法調(diào)用:如果在具有事務(wù)的方法內(nèi)部調(diào)用了另一個(gè)沒(méi)有使用@Transactional注解的方法,則被調(diào)用方法不會(huì)繼承事務(wù),即事務(wù)將被掛起,它將在調(diào)用返回后恢復(fù)。

  4. 事務(wù)邊界不一致:當(dāng)在一個(gè)方法中通過(guò)注解配置的事務(wù)與使用編程式事務(wù)管理方式(通過(guò)TransactionTemplatePlatformTransactionManager)管理的事務(wù)混合使用時(shí),事務(wù)可能會(huì)失效。這是因?yàn)镾pring無(wú)法同時(shí)應(yīng)用兩種不同的事務(wù)管理方式。

  5. ThreadLocal問(wèn)題:如果使用了并發(fā)編程中的ThreadLocal,例如在事務(wù)中使用了ThreadLocal保存狀態(tài),那么在多線程環(huán)境下,由于線程切換可能導(dǎo)致線程間的狀態(tài)共享問(wèn)題,從而破壞了事務(wù)的一致性。

  6. 方法級(jí)別的調(diào)用問(wèn)題:如果在同一個(gè)類中的一個(gè)使用@Transactional注解的方法調(diào)用了同一個(gè)類中另一個(gè)沒(méi)有使用注解的方法,事務(wù)將無(wú)法正常生效,因?yàn)镾pring使用代理對(duì)象來(lái)管理事務(wù),而調(diào)用同一個(gè)類中的方法將不會(huì)經(jīng)過(guò)代理,導(dǎo)致事務(wù)失效。

需注意的是,事務(wù)失效并不是Spring框架的設(shè)計(jì)缺陷,而是由于使用不當(dāng)或特定的情況下引起的。為了確保事務(wù)的正常工作,請(qǐng)確保在使用事務(wù)時(shí)遵循相關(guān)的最佳實(shí)踐,并注意上述可能導(dǎo)致事務(wù)失效的情況。

什么的是bean的自動(dòng)裝配,它有哪些方式?

Bean的自動(dòng)裝配是指Spring容器在創(chuàng)建Bean時(shí),自動(dòng)地根據(jù)特定規(guī)則在上下文中尋找匹配的依賴項(xiàng),并將其注入到Bean中。這樣可以減少配置文件的編寫(xiě),提高開(kāi)發(fā)效率,減少開(kāi)發(fā)人員的工作量。

Spring框架支持以下幾種Bean的自動(dòng)裝配方式:

1. **no(默認(rèn)):** 不使用自動(dòng)裝配,手動(dòng)指定依賴注入的方式(通過(guò)構(gòu)造器、setter方法等)。

2. **byName:** 根據(jù)bean的名稱進(jìn)行自動(dòng)裝配,Spring容器在上下文中查找與屬性名稱匹配的bean,然后進(jìn)行注入。

3. **byType:** 根據(jù)bean的類型進(jìn)行自動(dòng)裝配,Spring容器在上下文中查找與屬性類型匹配的bean,然后進(jìn)行注入。如果匹配的bean有多個(gè),則拋出異常。

4. **constructor:** 類似于byType,但是是應(yīng)用于構(gòu)造器參數(shù)的自動(dòng)裝配方式。

5. **autodetect:** Spring根據(jù)情況自動(dòng)選擇合適的自動(dòng)裝配方式,該方式會(huì)先byType,如果找不到則會(huì)byName。

自動(dòng)裝配可以通過(guò)在XML配置文件中的`<bean>`標(biāo)簽的`autowire`屬性來(lái)指定,也可以通過(guò)使用注解(如`@Autowired`、`@Resource`)來(lái)實(shí)現(xiàn)。在XML配置文件中使用自動(dòng)裝配的示例如下:

```xml
<bean id="beanA" class="com.example.BeanA" autowire="byName|byType|constructor|autodetect"/>
```

使用注解來(lái)實(shí)現(xiàn)自動(dòng)裝配的示例如下:


@Component
public class BeanA {
? ? @Autowired
? ? private BeanB beanB;

? ? // Getter and Setter
}

通過(guò)配置自動(dòng)裝配方式,Spring容器能夠根據(jù)預(yù)定義的規(guī)則來(lái)自動(dòng)解決Bean之間的依賴關(guān)系,簡(jiǎn)化了配置工作。開(kāi)發(fā)人員可以根據(jù)實(shí)際情況選擇合適的自動(dòng)裝配方式,提高了代碼的靈活性和可維護(hù)性。

spring是如何解決循環(huán)依賴的

Spring 在解決循環(huán)依賴時(shí)使用了三級(jí)緩存,分別是 singletonFactories、earlySingletonObjects 和 singletonObjects。這些緩存的使用可以幫助Spring在解決循環(huán)依賴問(wèn)題時(shí)進(jìn)行控制和管理。

  1. singletonFactories:在單例模式下,當(dāng) Spring 創(chuàng)建 Bean 時(shí),如果發(fā)現(xiàn)該 Bean 正在創(chuàng)建中,它會(huì)將這個(gè)創(chuàng)建中的 Bean 存儲(chǔ)在 singletonFactories 緩存中。這樣可以用來(lái)檢測(cè)循環(huán)依賴。

  2. earlySingletonObjects:當(dāng) Bean 的實(shí)例化完成但尚未完成初始化時(shí),該 Bean 會(huì)被存儲(chǔ)在 earlySingletonObjects 中。這樣可以確保其他 Bean 在初始化時(shí)可以引用到這些尚未初始化的 Bean。

  3. singletonObjects:一旦 Bean 創(chuàng)建完成并完成初始化后,Spring 將會(huì)將其存儲(chǔ)在 singletonObjects 緩存中。這樣其他的 Bean 可以直接引用到已經(jīng)初始化完成的 Bean 實(shí)例。

Spring 解決循環(huán)依賴的方法是通過(guò)依賴注入的過(guò)程中使用對(duì)象的代理。當(dāng)發(fā)現(xiàn)循環(huán)依賴時(shí),Spring 會(huì)創(chuàng)建一個(gè)提前暴露的、尚未完全初始化的代理對(duì)象作為依賴項(xiàng),以滿足對(duì)象之間的交叉引用。

具體的解決流程如下:

  1. 當(dāng) Spring 容器初始化時(shí),創(chuàng)建 Bean A 的過(guò)程中發(fā)現(xiàn)了循環(huán)依賴,需要解決 A 依賴于 B,而 B 又依賴于 A 的情況。

  2. 將正在創(chuàng)建 Bean A 的對(duì)象實(shí)例放入 singletonFactories 緩存中,表示該 Bean A 目前正在創(chuàng)建中。

  3. 接著創(chuàng)建 Bean B 的過(guò)程中,發(fā)現(xiàn) B 依賴于 A,但 A 正在創(chuàng)建中,因此從 singletonFactories 緩存中獲取正在創(chuàng)建的 Bean A 的對(duì)象實(shí)例。

  4. 當(dāng) Bean A 創(chuàng)建完成但尚未完成初始化時(shí),將其放入 earlySingletonObjects 緩存中,表示 Bean A 已經(jīng)實(shí)例化但尚未初始化。

  5. 繼續(xù)創(chuàng)建 Bean B,并注入 Bean A 的未完成初始化的實(shí)例。

  6. 最后完成 Bean A 和 Bean B 的創(chuàng)建和初始化后,將 Bean A 和 Bean B 放入 singletonObjects 緩存中,表示它們是已經(jīng)創(chuàng)建完成和初始化的 Bean 實(shí)例。

需要注意的是,雖然 Spring 能夠解決大多數(shù)情況下的循環(huán)依賴,但如果存在循環(huán)鏈,即 A 依賴于 B,B 依賴于 C,C 又依賴于 A,則 Spring 將無(wú)法解決這種循環(huán)依賴關(guān)系,會(huì)拋出 BeanCurrentlyInCreationException 異常。

總結(jié)一下,Spring 解決循環(huán)依賴的方式是通過(guò)提前暴露半初始化的代理對(duì)象,以滿足循環(huán)依賴關(guān)系中的引用,然后在完成所有 Bean 的創(chuàng)建和初始化后,將代理對(duì)象替換為實(shí)際對(duì)象。這樣就能夠成功解決循環(huán)依賴的問(wèn)題。

不能解決的幾種循環(huán)依賴

  1. 構(gòu)造函數(shù)循環(huán)依賴:如果Bean之間存在構(gòu)造函數(shù)注入,且存在循環(huán)依賴,Spring容器無(wú)法解決這種循環(huán)依賴,會(huì)拋出BeanCurrentlyInCreationException異常。

  2. 原型Bean循環(huán)依賴:如果兩個(gè)原型Bean之間存在循環(huán)依賴,Spring容器無(wú)法解決這種循環(huán)依賴,因?yàn)樵虰ean每次獲取都會(huì)創(chuàng)建新的對(duì)象實(shí)例,無(wú)法緩存起來(lái),也無(wú)法通過(guò)代理對(duì)象解決。

  3. @Async增強(qiáng)的bean循環(huán)依賴

pring中常見(jiàn)的幾種注解

Spring 框架中常見(jiàn)的注解包括但不限于:

  1. @Component:用于表示一個(gè)類是 Spring 容器管理的組件,通常與其他注解配合使用,如 @Repository、@Service@Controller 等。

  2. @Autowired:標(biāo)記在字段、構(gòu)造器、方法或者參數(shù)上,用于實(shí)現(xiàn)自動(dòng)裝配,通過(guò)類型匹配進(jìn)行依賴注入。

  3. @Qualifier:與 @Autowired 配合使用,在存在多個(gè)具有相同類型的實(shí)例時(shí),通過(guò)指定名稱來(lái)選擇具體的實(shí)例進(jìn)行注入。

  4. @Value:用于注入簡(jiǎn)單屬性值,支持 SpEL 表達(dá)式,例如 @Value("${app.title}")。

  5. @Configuration:標(biāo)記在配置類上,表示該類是 Spring 的配置類,會(huì)告訴 Spring 應(yīng)用上下文去加載 Bean 定義。

  6. @Bean:標(biāo)記在方法上,將方法的返回對(duì)象注冊(cè)為一個(gè) Bean,該對(duì)象會(huì)被 Spring IoC 容器管理。

  7. @ComponentScan:配置包掃描路徑,用于自動(dòng)掃描并注冊(cè)標(biāo)記有 @Component 的類作為 Spring Bean。

  8. @RequestMapping:定義請(qǐng)求 URL 映射,用于處理 Web 請(qǐng)求,通常用在 Controller 類的方法上。

  9. @Service、@Repository、@Controller:用于添加更多細(xì)分類型的組件注解,讓 Spring 在掃描注解時(shí)能更清楚地區(qū)分各種組件類型。

  10. @Scope:定義 Bean 的作用域,例如 Singleton、Prototype、Request、Session 等。

  11. @Aspect、@Pointcut@Before、@After、@Around、@AfterReturning、@AfterThrowing:用于定義切面和通知的注解,實(shí)現(xiàn)面向切面編程(AOP)。

  12. @Transactional:用于聲明事務(wù)處理的方法或類,標(biāo)注在方法或類上,指明該方法或類需要進(jìn)行事務(wù)處理。

這些注解是 Spring 框架中常見(jiàn)且重要的注解,它們能夠幫助我們簡(jiǎn)化配置、實(shí)現(xiàn)依賴注入、定義 Bean、處理 Web 請(qǐng)求、實(shí)現(xiàn)事務(wù)管理等。

當(dāng)然,還有更多在 Spring 框架中常見(jiàn)和常用的注解:

  1. @RequestMapping:在控制器類或方法上使用,用于映射 Web 請(qǐng)求的 URL 路徑和處理方法。

  2. @PathVariable:在方法參數(shù)上使用,用于從請(qǐng)求的 URL 中獲取路徑變量的值。

  3. @RequestParam:在方法參數(shù)上使用,用于從請(qǐng)求的參數(shù)中獲取值。

  4. @RequestHeader:在方法參數(shù)上使用,用于從請(qǐng)求頭中獲取值。

  5. @ResponseBody:通常在控制器方法上使用,用于將方法返回的對(duì)象轉(zhuǎn)換為指定的響應(yīng)格式(如 JSON)并作為響應(yīng)返回。

  6. @ModelAttribute:用于綁定請(qǐng)求參數(shù)到方法參數(shù)或方法的返回對(duì)象。

  7. @Valid:通常結(jié)合 JSR-303 標(biāo)準(zhǔn)的驗(yàn)證注解一起使用,用于驗(yàn)證方法參數(shù)或方法返回對(duì)象的數(shù)據(jù)的合法性。

  8. @InitBinder:用于配置用于表單數(shù)據(jù)綁定的 WebDataBinder,通常用于注冊(cè)自定義的屬性編輯器或驗(yàn)證器。

  9. @RestController:一個(gè)方便的組合注解,結(jié)合了 @Controller@ResponseBody,用于定義 RESTful 風(fēng)格的控制器。

  10. @ConfigurationProperties:用于將屬性綁定到配置類中的屬性上,可以用于統(tǒng)一管理項(xiàng)目的配置參數(shù)。

  11. @Async:標(biāo)記在方法上,允許方法異步執(zhí)行,可以提升系統(tǒng)的性能和并發(fā)處理能力。

  12. @Enable* 系列注解:如 @EnableCaching、@EnableScheduling、@EnableAsync 等,用于啟用相應(yīng)的特性或功能。

這些注解在不同的場(chǎng)景中扮演著重要的角色,讓我們能夠更便捷地進(jìn)行開(kāi)發(fā)和配置,減少了大量的樣板代碼和配置工作。它們?yōu)?Spring 提供了更強(qiáng)大的功能和靈活性,簡(jiǎn)化了開(kāi)發(fā)過(guò)程。

spring、springmvc、springboot的區(qū)別是什么?

spring和springMvc:

  1. spring是一個(gè)一站式的輕量級(jí)的java開(kāi)發(fā)框架,核心是控制反轉(zhuǎn)(IOC)和面向切面(AOP),針對(duì)于開(kāi)發(fā)的WEB層(springMvc)、業(yè)務(wù)層(Ioc)、持久層(jdbcTemplate)等都提供了多種配置解決方案;

  2. springMvc是spring基礎(chǔ)之上的一個(gè)MVC框架,主要處理web開(kāi)發(fā)的路徑映射和視圖渲染,屬于spring框架中WEB層開(kāi)發(fā)的一部分;

springMvc和springBoot:

1、springMvc屬于一個(gè)企業(yè)WEB開(kāi)發(fā)的MVC框架,涵蓋面包括前端視圖開(kāi)發(fā)、文件配置、后臺(tái)接口邏輯開(kāi)發(fā)等,XML、config等配置相對(duì)比較繁瑣復(fù)雜;

2、springBoot框架相對(duì)于springMvc框架來(lái)說(shuō),更專注于開(kāi)發(fā)微服務(wù)后臺(tái)接口,不開(kāi)發(fā)前端視圖,同時(shí)遵循默認(rèn)優(yōu)于配置,簡(jiǎn)化了插件配置流程,不需要配置xml,相對(duì)springmvc,大大簡(jiǎn)化了配置流程;

總結(jié):

1、Spring 框架就像一個(gè)家族,有眾多衍生產(chǎn)品例如 boot、security、jpa等等。但他們的基礎(chǔ)都是Spring的ioc、aop等. ioc 提供了依賴注入的容器, aop解決了面向橫切面編程,然后在此兩者的基礎(chǔ)上實(shí)現(xiàn)了其他延伸產(chǎn)品的高級(jí)功能;

2、springMvc主要解決WEB開(kāi)發(fā)的問(wèn)題,是基于Servlet 的一個(gè)MVC框架,通過(guò)XML配置,統(tǒng)一開(kāi)發(fā)前端視圖和后端邏輯;

3、由于Spring的配置非常復(fù)雜,各種XML、JavaConfig、servlet處理起來(lái)比較繁瑣,為了簡(jiǎn)化開(kāi)發(fā)者的使用,從而創(chuàng)造性地推出了springBoot框架,默認(rèn)優(yōu)于配置,簡(jiǎn)化了springMvc的配置流程;但區(qū)別于springMvc的是,springBoot專注于單體微服務(wù)接口開(kāi)發(fā),和前端解耦,雖然springBoot也可以做成springMvc前后臺(tái)一起開(kāi)發(fā),但是這就有點(diǎn)不符合springBoot框架的初衷了;

springmvc工作流程是什么?

當(dāng)發(fā)起請(qǐng)求時(shí)被前置的控制器攔截到請(qǐng)求,根據(jù)請(qǐng)求參數(shù)生成代理請(qǐng)求,找到請(qǐng)求對(duì)應(yīng)的實(shí)際控制器,控制器處理請(qǐng)求,創(chuàng)建數(shù)據(jù)模型,訪問(wèn)數(shù)據(jù)庫(kù),將模型響應(yīng)給中心控制器,控制器使用模型與視圖渲染視圖結(jié)果,將結(jié)果返回給中心控制器,再將結(jié)果返回給請(qǐng)求者。

1、DispatcherServlet表示前置控制器,是整個(gè)SpringMVC的控制中心。用戶發(fā)出請(qǐng)求,DispatcherServlet接收請(qǐng)求并攔截請(qǐng)求。

2、HandlerMapping為處理器映射。DispatcherServlet調(diào)用HandlerMapping,HandlerMapping根據(jù)請(qǐng)求url查找Handler。

3、返回處理器執(zhí)行鏈,根據(jù)url查找控制器,并且將解析后的信息傳遞給DispatcherServlet

4、HandlerAdapter表示處理器適配器,其按照特定的規(guī)則去執(zhí)行Handler。

5、執(zhí)行handler找到具體的處理器

6、Controller將具體的執(zhí)行信息返回給HandlerAdapter,如ModelAndView。

7、HandlerAdapter將視圖邏輯名或模型傳遞給DispatcherServlet。

8、DispatcherServlet調(diào)用視圖解析器(ViewResolver)來(lái)解析HandlerAdapter傳遞的邏輯視圖名。 9、視圖解析器將解析的邏輯視圖名傳給DispatcherServlet。

10、DispatcherServlet根據(jù)視圖解析器解析的視圖結(jié)果,調(diào)用具體的視圖,進(jìn)行試圖渲染

11、將響應(yīng)數(shù)據(jù)返回給客戶端

springmvc的九大組件有哪些?

Spring MVC(Model-View-Controller)是一個(gè)基于Java的MVC框架,用于開(kāi)發(fā)Web應(yīng)用程序。下面是Spring MVC的九大組件:

  1. DispatcherServlet(調(diào)度器):是Spring MVC的核心組件,接收客戶端的請(qǐng)求并將其分派給相應(yīng)的處理器。

  2. HandlerMapping(處理器映射器):負(fù)責(zé)根據(jù)請(qǐng)求的URL映射到相應(yīng)的處理器(Controller)。

  3. HandlerAdapter(處理器適配器):將處理器(Controller)適配為一個(gè)能夠處理請(qǐng)求的處理器對(duì)象,并調(diào)用其處理方法。

  4. HandlerInterceptor(處理器攔截器):對(duì)請(qǐng)求進(jìn)行預(yù)處理和后處理。在請(qǐng)求被調(diào)度到處理器之前和之后,可以執(zhí)行一些公共的任務(wù),如身份驗(yàn)證、日志記錄等。

  5. ViewResolver(視圖解析器):根據(jù)邏輯視圖名(View Name)解析視圖對(duì)象,可以是JSP、Thymeleaf、Freemarker等等。

  6. View(視圖):負(fù)責(zé)渲染模型數(shù)據(jù),并將其呈現(xiàn)給用戶。常見(jiàn)的視圖技術(shù)包括JSP、HTML、JSON等。

  7. ModelAndView(模型和視圖):將模型數(shù)據(jù)與視圖對(duì)象封裝在一起,以便向視圖傳遞數(shù)據(jù)并指示要呈現(xiàn)的視圖。

  8. HandlerExceptionResolver(異常解析器):處理請(qǐng)求過(guò)程中產(chǎn)生的異常。將異常轉(zhuǎn)換為統(tǒng)一的錯(cuò)誤視圖或錯(cuò)誤消息。

  9. MultipartResolver(多部分解析器):處理文件上傳請(qǐng)求,解析多部分請(qǐng)求,獲取上傳的文件和表單數(shù)據(jù)。

這些組件共同協(xié)作,使得Spring MVC能夠接收、處理和響應(yīng)客戶端的請(qǐng)求,并以MVC模式將應(yīng)用程序的邏輯、數(shù)據(jù)和視圖進(jìn)行了清晰的分離。

Spring框架中有哪些不同類型的事件

Spring 提供了以下5種標(biāo)準(zhǔn)的事件:

上下文更新事件(ContextRefreshedEvent):在調(diào)用ConfigurableApplicationContext 接口中的refresh()方法時(shí)被觸發(fā)。

上下文開(kāi)始事件(ContextStartedEvent):當(dāng)容器調(diào)用ConfigurableApplicationContext的Start()方法開(kāi)始/重新開(kāi)始容器時(shí)觸發(fā)該事件。

上下文停止事件(ContextStoppedEvent):當(dāng)容器調(diào)用ConfigurableApplicationContext的Stop()方法停止容器時(shí)觸發(fā)該事件。

上下文關(guān)閉事件(ContextClosedEvent):當(dāng)ApplicationContext被關(guān)閉時(shí)觸發(fā)該事件。容器被關(guān)閉時(shí),其管理的所有單例Bean都被銷毀。

請(qǐng)求處理事件(RequestHandledEvent):在Web應(yīng)用中,當(dāng)一個(gè)http請(qǐng)求(request)結(jié)束觸發(fā)該事件。如果一個(gè)bean實(shí)現(xiàn)了ApplicationListener接口,當(dāng)一個(gè)ApplicationEvent 被發(fā)布以后,bean會(huì)自動(dòng)被通知。

http://aloenet.com.cn/news/47024.html

相關(guān)文章:

  • 知名高端網(wǎng)站設(shè)計(jì)企業(yè)百度網(wǎng)站檢測(cè)
  • 卡盟網(wǎng)站怎么做圖片素材網(wǎng)站seo方法
  • 網(wǎng)站搜索怎么做常見(jiàn)的網(wǎng)絡(luò)營(yíng)銷推廣方式有哪些
  • 建程網(wǎng)app下載西安seo和網(wǎng)絡(luò)推廣
  • 便宜 虛擬主機(jī)sem 優(yōu)化軟件
  • 基金管理公司司網(wǎng)站建設(shè)要求國(guó)際新聞今天
  • wordpress扒站工具北京網(wǎng)站制作公司
  • 網(wǎng)站建設(shè)價(jià)錢差異外貿(mào)接單平臺(tái)哪個(gè)最好
  • 做網(wǎng)站如何導(dǎo)入信用卡付款一個(gè)產(chǎn)品的市場(chǎng)營(yíng)銷策劃方案
  • ??诰W(wǎng)站開(kāi)發(fā)公司電話建立一個(gè)網(wǎng)站的費(fèi)用
  • 杭州濱江網(wǎng)站建設(shè)公司信息流優(yōu)化師面試常見(jiàn)問(wèn)題
  • go 是做網(wǎng)站的嗎廣州seo推薦
  • 網(wǎng)站開(kāi)發(fā)知識(shí)體系推廣普通話的意義簡(jiǎn)短
  • 尋花問(wèn)柳專注做一家男人愛(ài)的網(wǎng)站百度云網(wǎng)盤(pán)資源搜索
  • 網(wǎng)絡(luò)營(yíng)銷做私活網(wǎng)站智慧軟文發(fā)稿平臺(tái)官網(wǎng)
  • asp.net 網(wǎng)站備份免費(fèi)域名注冊(cè)網(wǎng)站
  • 做網(wǎng)站抄代碼免費(fèi)seo軟件
  • 建設(shè)網(wǎng)站制作網(wǎng)站營(yíng)銷方案模板
  • 大連今天最新通知電商運(yùn)營(yíng)seo
  • 哈爾濱網(wǎng)站設(shè)計(jì)有哪些步驟寧波網(wǎng)站推廣聯(lián)系方式
  • 企業(yè)網(wǎng)站基本信息早教優(yōu)化深圳seo
  • 福建省做鞋批發(fā)網(wǎng)站百度開(kāi)放云平臺(tái)
  • 官方網(wǎng)站首頁(yè)在線seo推廣軟件
  • php怎么做多個(gè)網(wǎng)站網(wǎng)站關(guān)鍵詞快速排名技術(shù)
  • 河北建設(shè)集團(tuán)官網(wǎng)如何做好seo基礎(chǔ)優(yōu)化
  • 一級(jí)a做片性視頻.網(wǎng)站在線觀看鄭州seo排名第一
  • 寵物寄養(yǎng)網(wǎng)站畢業(yè)設(shè)計(jì)重慶百度關(guān)鍵詞優(yōu)化軟件
  • 網(wǎng)站建設(shè)公司排名搜索大全
  • 鄂州做網(wǎng)站報(bào)價(jià)谷歌搜索引擎免費(fèi)入口鏡像
  • 廈門企業(yè)網(wǎng)站建設(shè)補(bǔ)貼百度官網(wǎng)首頁(yè)網(wǎng)址