溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點(diǎn)擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

Spring底層核心原理是什么

發(fā)布時(shí)間:2023-04-19 15:43:54 來源:億速云 閱讀:99 作者:iii 欄目:開發(fā)技術(shù)

本文小編為大家詳細(xì)介紹“Spring底層核心原理是什么”,內(nèi)容詳細(xì),步驟清晰,細(xì)節(jié)處理妥當(dāng),希望這篇“Spring底層核心原理是什么”文章能幫助大家解決疑惑,下面跟著小編的思路慢慢深入,一起來學(xué)習(xí)新知識吧。

Spring底層核心原理

下面這幾行代碼是一個(gè)Spring的入門代碼,第一行是通過java配置類 注解的方式創(chuàng)建一個(gè)Spring容器,第二行是通過XML配置文件的方式創(chuàng)建一個(gè)Spring容器

AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
//ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("spring.xml");
UserService userService = (UserService) context.getBean("userService");
userService.test();

最后兩行代碼就是從Spring容器中拿一個(gè)Bean對象并執(zhí)行方法。那么Spring是如何創(chuàng)建一個(gè)Bean對象的嘞?

Bean的生命周期

  • 推斷構(gòu)造方法,并執(zhí)行得到普通對象

  • 依賴注入

  • aware回調(diào)

  • 初始化前

執(zhí)行BeanPostProcessor接口中的postProcessBeforeInitialization()方法

  • 初始化

執(zhí)行有@PostConstruct注解的方法執(zhí)行

InitializingBean接口中的afterPropertiesSet()方法

執(zhí)行XML配置文件中init-method屬性指定的方法

  • 初始化后

執(zhí)行BeanPostProcessor接口中的postProcessAfterInitialization()方法

  • 普通對象/代理對象 存入容器中

  • 使用

  • 銷毀

執(zhí)行DisposableBean接口的destroy()方法

@PreDestroy注解的方法

XML 配置文件中destroy-method屬性指定的方法

推斷構(gòu)造方法

如果沒有寫構(gòu)造方法,那么Spring會執(zhí)行默認(rèn)空參的構(gòu)造方法

如果顯示寫了一個(gè)構(gòu)造方法,那么Spring就會使用這個(gè)構(gòu)造方法,構(gòu)造方法中如果有參數(shù)那么會進(jìn)行依賴注入

如果顯示寫了多個(gè)構(gòu)造方法并有空參的構(gòu)造方法時(shí),會執(zhí)行空參的構(gòu)造方法

如果顯示寫了多個(gè)構(gòu)造方法沒有空參的構(gòu)造方法時(shí),運(yùn)行時(shí)會報(bào)錯(cuò)。解決方法是在要執(zhí)行的構(gòu)造方法上加@Autowired注解

AOP原理

cjlib和jdk兩種動(dòng)態(tài)代理的實(shí)現(xiàn)都是有一個(gè)target屬性來存儲普通對象,代理對象中重寫要執(zhí)行的方法,首先執(zhí)行增強(qiáng)邏輯,然后通過target屬性去執(zhí)行目標(biāo)方法。偽代碼如下:

public class UserServiceProxy extends UserService{
    private UserService target;
    public void test(){
        // TODO 增強(qiáng)業(yè)務(wù)
        target.test();
        // TODO 增強(qiáng)業(yè)務(wù)
    }
}

那么如何判斷一個(gè)Bean是否需要進(jìn)行AOP創(chuàng)建一個(gè)普通對象嘞?

  • 遍歷所有有@Aspect注解的切面Bean

  • 遍歷所有的方法

  • 判斷方法上的切點(diǎn)表達(dá)式是否和當(dāng)前正在創(chuàng)建的Bean匹配

  • 如果匹配則把這個(gè)切面中增強(qiáng)方法存入一個(gè)Map緩存中

真正要執(zhí)行代理對象的方法時(shí)會從緩存中取出相應(yīng)的增強(qiáng)邏輯來執(zhí)行,再去執(zhí)行目標(biāo)方法。

Spring事務(wù)

Spring中如果要使用事務(wù)需要配置一個(gè)JdbcTemplate和一個(gè)事務(wù)管理器,它們倆都需要配置DataSource。

@ComponentScan("com.hs")
@Configuration
public class AppConfig {
   @Bean
   public JdbcTemplate jdbcTemplate() {
      return new JdbcTemplate(dataSource());
   }
   @Bean
   public PlatformTransactionManager transactionManager() {
      DataSourceTransactionManager transactionManager = new DataSourceTransactionManager();
      transactionManager.setDataSource(dataSource());
      return transactionManager;
   }
   @Bean
   public DataSource dataSource() {
      DriverManagerDataSource dataSource = new DriverManagerDataSource();
      dataSource.setUrl("jdbc:mysql://127.0.0.1:3306/hs?characterEncoding=utf-8&useSSL=false&serverTimezone=Asia/Shanghai");
      dataSource.setUsername("root");
      dataSource.setPassword("123456");
      return dataSource;
   }
}

Spring事務(wù)大致執(zhí)行流程如下:

  • 判斷要執(zhí)行的方法上是否存在@Transcational注解

  • 如果存在則通過事務(wù)管理器創(chuàng)建一個(gè)connection連接對象

  • autoCommit設(shè)置為false

  • 去執(zhí)行目標(biāo)方法target.method()

  • 如果出現(xiàn)了異常則回滾rollback(),沒有異常則提交commit()

如果上面的配置類中不加@Configuration注解,那么Spring的事務(wù)會失效。原因如下:

JdbcTemplate和事務(wù)管理器都需要DataSource,都會調(diào)用dataSource()獲取。如果不加@Configuration注解,那么他們倆獲取的DataSource就不是同一個(gè)。

代理對象中操作的是事務(wù)管理器的連接對象,而業(yè)務(wù)方法卻是使用的JdbcTemplate,所以就導(dǎo)致了Spring事務(wù)失效。

而如果加上了@Configuration注解,在調(diào)用dataSource()時(shí)會先去Spring容器中找DataSource,如果沒找到才回去調(diào)用方法創(chuàng)建一個(gè)。

讀到這里,這篇“Spring底層核心原理是什么”文章已經(jīng)介紹完畢,想要掌握這篇文章的知識點(diǎn)還需要大家自己動(dòng)手實(shí)踐使用過才能領(lǐng)會,如果想了解更多相關(guān)內(nèi)容的文章,歡迎關(guān)注億速云行業(yè)資訊頻道。

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI