最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

深入探究Spring底層核心原理

 更新時(shí)間:2023年04月19日 10:34:08   作者:胡尚  
理解IOC與AOP的實(shí)現(xiàn)機(jī)制,優(yōu)化應(yīng)用性能與可維護(hù)性。Spring通過(guò)IOC容器管理Bean,AOP實(shí)現(xiàn)切面編程,支持事務(wù)管理、ORM框架等。深入理解Spring原理,可以幫助我們更好地使用Spring框架,提高開(kāi)發(fā)效率與質(zhì)量

Spring底層核心原理

下面這幾行代碼是一個(gè)Spring的入門(mén)代碼,第一行是通過(guò)java配置類(lèi) 注解的方式創(chuàng)建一個(gè)Spring容器,第二行是通過(guò)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對(duì)象并執(zhí)行方法。那么Spring是如何創(chuàng)建一個(gè)Bean對(duì)象的嘞?

Bean的生命周期

  • 推斷構(gòu)造方法,并執(zhí)行得到普通對(duì)象
  • 依賴注入
  • aware回調(diào)
  • 初始化前

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

  • 初始化

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

InitializingBean接口中的afterPropertiesSet()方法

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

  • 初始化后

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

  • 普通對(duì)象/代理對(duì)象 存入容器中
  • 使用
  • 銷(xiāo)毀

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

@PreDestroy注解的方法

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

推斷構(gòu)造方法

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

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

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

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

AOP原理

cjlib和jdk兩種動(dòng)態(tài)代理的實(shí)現(xiàn)都是有一個(gè)target屬性來(lái)存儲(chǔ)普通對(duì)象,代理對(duì)象中重寫(xiě)要執(zhí)行的方法,首先執(zhí)行增強(qiáng)邏輯,然后通過(guò)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è)普通對(duì)象嘞?

  • 遍歷所有有@Aspect注解的切面Bean
  • 遍歷所有的方法
  • 判斷方法上的切點(diǎn)表達(dá)式是否和當(dāng)前正在創(chuàng)建的Bean匹配
  • 如果匹配則把這個(gè)切面中增強(qiáng)方法存入一個(gè)Map緩存中

真正要執(zhí)行代理對(duì)象的方法時(shí)會(huì)從緩存中取出相應(yīng)的增強(qiáng)邏輯來(lái)執(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注解
  • 如果存在則通過(guò)事務(wù)管理器創(chuàng)建一個(gè)connection連接對(duì)象
  • autoCommit設(shè)置為false
  • 去執(zhí)行目標(biāo)方法target.method()
  • 如果出現(xiàn)了異常則回滾rollback(),沒(méi)有異常則提交commit()

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

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

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

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

到此這篇關(guān)于深入探究Spring底層核心原理的文章就介紹到這了,更多相關(guān)Spring底層原理內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

最新評(píng)論

安达市| 娄烦县| 布尔津县| 黔南| 台南市| 大厂| 仁布县| 沾益县| 凯里市| 宁津县| 五寨县| 剑河县| 哈巴河县| 唐山市| 喀喇沁旗| 苏尼特左旗| 灌阳县| 无棣县| 邵东县| 北海市| 乌什县| 怀仁县| 鹰潭市| 康马县| 东兴市| 山丹县| 昔阳县| 毕节市| 孟连| 临沭县| 汾阳市| 余干县| 个旧市| 乌拉特前旗| 衡南县| 祁阳县| 涪陵区| 叙永县| 三河市| 勐海县| 友谊县|