Spring源码学习Day01

Spring源码学习Day01


前言

Spring源码学习Day01,描述错误或不严谨之处,请指正


一、配置方式

Spring的XML配置方式

ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("spring.xml");
StudentService studentService = (StudentService) context.getBean("studentService");
studnetService.learn();

SpringBoot使用类的配置方式

AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
StudentService studentService = (StudentService) context.getBean("studentService");
studnetService.learn();

二、getBean()如何找到类

context.getBean("studentService");

大致步骤:
1,解析AppConfig.class,得到扫描路径;
2,遍历扫描路径下的所有的Java类,如果发现某些类上存在@Component,@Service等这些注解,就将这些类记录到一个Map对象中,类似于Map<String, Class>;
3,Map对象中的key是Spring根据某种规则生成的对象名称,也就是beanName,而value值就是对应的类;
4,调用context.getBean(“xxxx”)方法时,即可根据传入的key,找到对应的类了。


三、Spring是如何创建Bean对象的

1,大致步骤:

推断构造方法 ➡ 依赖注入 ➡ Aware接口 ➡ @PostConstruct(初始化前)➡ InitializingBean接口(初始化)➡ AOP(初始化后)➡ 代理对象 ➡ bean对象
1,会调用当前对象的构造方法,默认调用无参构造方法,存在多个构造方法时,Spring需要进行“推断构造方法”,选择其中一个构造方法。
2,扫描当前对象哪些属性上有@Autowired注解,进行依赖注入。
3,判断当前对象是否实现了Aware接口,如BeanNameAware,BeanClassLoaderAware,BeanFactoryAware接口,如实现,则Spring会调用其实现的setBeanName(),setBeanClassLoader(),setBeanFactory()方法,Aware回调。
4,扫描当前对象有哪些方法上有@PostConstruct注解,执行这些方法,这一步为初始化前。
5,判断当前对象是否实现了InitializingBean接口,如实现了,执行afterPropertiesSe()方法,这一步为初始化。
6,判断当前对象是否进行了AOP,若需要AOP,则生成动态代理对象,这一步为初始化后;若不需要AOP,则Bean对象创建完成。

2,Bean对象创建完成后:

1,如果Bean对象是单例的,则会将Bean对象存入到Map中,类似于Map<String, Object>,其中key为beanName,value为bean对象,这样,下次获取Bean对象时,直接通过key找到value即可;
2,如果Bean对象是原型的,那么Bean对象不需要存入到Map中,每次调用getBean()方法时,都会执行上述的过程,创建一个新的Bean对象。

3,推断构造方法

Spring如何选择构造方法,有下述两种情况
1,类中只有一个构造方法,Spring只能调用这个构造方法(有参或者无参)。
2,类中有多个构造方法:
(1)有一个无参构造法,Spring则会调用这个无参的构造方法(默认)。
(2)没有无参构造方法,则Spring会报错。
3,如果存在一个加了@Autowired注解的构造方法,那么Spring则会选择这个注入的构造方法,如果这个构造方法是有参数的,那么Spring会根据参数类型,参数名称找到容器中对应的对象,详细过程如下:
(1)先根据参数对象类型去Spring容器中匹配,如果唯一匹配,则直接注入。
(2)如果类型匹配多个,则再根据参数名称匹配,如果唯一匹配,则直接注入。
(3)如果仍然未找到,则会报错,无法创建Bean对象。

总之,上述Spring如何选择构造方法的过程,就叫做“推断构造方法”。


四、AOP大致流程

1,创建完一个Bean对象,Spring是如何判断当前Bean对象是否需要进行AOP,即是否需要进行动态代理,AOP的大致流程如下:

1,扫描所有的切面类。
2,判断切面类中哪些方法是否加了@Before,@After等注解,找到所有的切面方法。
3,根据切面方法的Pointcut,判断是否是当前的Bean对象类型,如是,则需要进行AOP。

2,根据Cglib进行AOP的大致流程:

1,创建一个StudentServiceProxy代理类,继承StudentService类。
2,重写父类中的方法。
3,代理类StudentServiceProxy中的target对象,实际上是普通对象,或者说是被代理的那个StudentService对象,该对象是经过推断构造方法,依赖注入,初始化等过程创建完成的。
4,通过StudentServiceProxy代理类调用父类方法,实际上是先执行切面类中的@Before方法,然后再通过target对象调用test()方法。

简而言之,上述代理类执行过程如下,StudentService代理对象.test() ➡ 执行切面逻辑 ➡ target.test()方法。


五、Spring事务

当我们在一个方法上加上了@Transaction注解时,就表示开启了Spring事务,这个方法所属的类,就会生成代理类。
Spring事务的代理类的执行大致过程如下:
1,判断当前类中的方法,是否存在@Transaction注解。
2,若存在,则事务管理器(TransactionManager)会新建一个数据库连接。
3,修改数据库连接的autocommit为false。
4,执行target.test(),即执行程序员自己写的方法,执行SQL语句。
5,如果抛出异常,则进行事务的回滚,否则正常提交。

Spring事务是否会失效的标准:某个加了@Transaction注解的方法在被调用时,是否是直接被代理对象调用的,如果是,则事务会生效,如果不是,则事务会失效。


总结

本节课,对Spring的配置方式有了个简单的了解,比如有XML方式和配置类方式,但是不管是哪张配置方式,在Spring中,通过context.getBean()方法获取Bean对象的原理都是大致相同的,都是创建了一个Map<String,Class>来保存对象名称(key)以及对应的类(value),然后通过key获得value;接着,进一步了解了Spring创建Bean对象的大致流程,粗略有7步或8步,在这一流程中,又对其中的推断构造方法,AOP动态代理进行了展开说明,如Spring是如何选择构造方法,怎么判断一个Bean对象是否需要进行动态代理,以及Cglib动态代理的大概过程;最后,由AOP引出了在Spring事务中,是如何运用动态代理的。

PS:上述整理,是本人经过一节网课学习后,进行复习整理,如果有错误或不准确的地方,还请各位大佬们指出。

  • 24
    点赞
  • 30
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
对于学习Spring源码的网站,可以参考以下链接: 1. Spring官方网站:https://spring.io/ 在官方网站上,你可以找到关于Spring的所有文档、教程和源码下载链接。它是学习Spring的首要资源。 2. GitHub上的Spring源码仓库:https://github.com/spring-projects/spring-framework 这是Spring源码的官方GitHub仓库,你可以在这里找到最新的Spring源码,并参与到开发讨论中。 3. CSDN博客:https://blog.csdn.net/navyfrost/article/details/102919323 这是一篇关于Spring源码学习的博客文章,作者分享了学习Spring源码的心得和方法,并提供了一些学习资源和案例。 希望以上资源可以帮助你开始学习Spring源码。祝你学习顺利!<span class="em">1</span><span class="em">2</span><span class="em">3</span><span class="em">4</span> #### 引用[.reference_title] - *1* [Spring源码学习加注释,方便学习.zip](https://download.csdn.net/download/weixin_47367099/85350853)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] - *2* *3* *4* [Spring源码学习系列——源码下载和环境](https://blog.csdn.net/shangguoli/article/details/124710529)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值