Spring入门系列:浅析知识点

简介: 本文介绍了学习Spring源码前需要掌握的核心知识点,包括IOC、AOP、Bean生命周期、初始化和Transaction事务。通过Hello World示例,讲解了如何使用Spring,并指出了深入了解Spring内部机制的方向。

前言

讲解Spring之前,我们首先梳理下Spring有哪些知识点可以进行入手源码分析,比如:

  1. Spring IOC依赖注入
  2. Spring AOP切面编程
  3. Spring Bean的声明周期底层原理
  4. Spring 初始化底层原理
  5. Spring Transaction事务底层原理

Hello World

通过这些知识点,后续我们慢慢在深入Spring的使用及原理剖析,为了更好地理解Spring,我们需要先了解一个最简单的示例——Hello World。在学习任何框架和语言之前,Hello World都是必不可少的。

//在以前大家都是spring.xml进行注入bean后供Spring框架解析
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("spring.xml");
UserService userService = (UserService) context.getBean("userService");
userService.test();

spring.xml中的内容为:

<context:component-scan base-package="com.zhouyu"/>
<bean id="userService" class="com.zhouyu.service.UserService"/>

如果对上面的代码或者xml形式很陌生,再看下面一种代码,也是目前流行的一种形式

//通过我们的配置类进行注入bean并解析
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(MySpringConfig.class);
//ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("spring.xml");
UserService userService = (UserService) context.getBean("userService");
userService.test()

MySpringConfig中的内容为:

@ComponentScan("com.xiaoyu")
public class MySpringConfig {
    @Bean
    public UserService userService(){
        return new UserService();
    }
}

相信很多人都会对上面的代码不陌生,那我们来看下这三行代码都做了那些工作:

  1. 构造一个ClassPathXmlApplicationContext类解析配置文件 或者AnnotationConfigApplicationContext类 解析配置类,那么调用该构造方法除开会实例化得到一个对象,还会做哪些事情?
  2. 从context中获取一个名字为"userService"的userService对象,那么为什么输入一个字符串就可以得到对象呢,好像跟Map有些类似,getBean()又是如何实现的?返回的UserService对象和我们自己直接new的UserService对象有区别吗?
  3. 通过获取到的UserService对象调用test方法,这个不难理解。

虽然我们目前很少直接使用这种方式来使用Spring,而是使用Spring MVC或者Spring Boot,但是它们都是基于上面这种方式的,都需要在内部去创建一个
ApplicationContext的,只不过:

  1. Spring MVC创建的是XmlWebApplicationContext,和ClassPathXmlApplicationContext类似,都是基于XML配置的
  2. Spring Boot创建的是AnnotationConfigApplicationContext

下面我们将重点讲解Spring对bean的创建,也就是大家常说的Bean的生命周期。虽然我们只是入门级别的学习,但我们仍将深入探讨流程,但不会涉及到具体的源码分析。在后续的源码分析系列中,我们将着重分析每一个知识点。

Bean的创建过程

那么,Spring是如何创建一个Bean的呢?这就是Bean的生命周期。其大体过程如下:

  1. 首先当我们的对象类被配置类使用@Bean又或者被包路径扫描到将会进入创建Bean的流程
  2. Spring会使用对象构造器进行实例化创建个对象
  3. 开始解析对象的属性是否有被@autowired注解修饰,如果有会从Spring的单例池中获取对象并进行注入就是属性赋值(依赖注入)
  4. 依赖注入后会判断对象时否实现了各种Aware接口,如:BeanNameAware接口、 BeanClassLoaderAware接口、BeanFactoryAware接口等,并自动调用其中的需要被实现的方法(Aware回调)
  5. 回调方法实现后,Spring会判断是否有包含了@postconstruct注解方法,如果有会进行调用此方法(实例化前)
  6. Spring判断对象是否实现了InitializingBean接口,实例化对象就必须调用afterPropertiesSet()方法,也是Spring帮调用的(初始化)
  7. 最后,Spring会判断我们的对象是否需要进行AOP,如果不需要那么Bean到此就完事,如果需要,Spring还会自动动态代理并生成一个代理对象做为Bean(初始化后)

通过以上步骤,我们可以了解到创建的对象可能存在两种结果。如果不需要AOP,Bean就是通过构造方法创建的对象;如果需要AOP,Bean就是代理类所实例化得到的对象,而不是构造方法所得到的对象。

Bean创建后:

  1. 如果当前Bean是单例的(默认),Spring在初始化Bean之后,会将当前已经初始化之后的对象放入Spring管理的单例缓存池中(Map结构),这样如果其他对象需要注入这个对象时,会直接从单例缓存池中取出来,进行属性注入。
  2. 如果当前Bean是多例的(即被@Scope("prototype")注解修饰),每次获取对象时,或者被其他对象引用时都会重新走一遍创建Bean的逻辑来创建一个新对象。这意味着,每次获取该Bean时都会创建一个新的实例,而不是从缓存池中获取已有的实例。因此,多例Bean的对象是不共享的,每个对象都是独立的。

构造器的初始化

在Spring中,每个对象都会有默认的构造器。但是在实际业务中,有时候会存在多个构造器的情况。那么,Spring如何去选择使用哪个构造器去创建对象呢?
Spring的判断逻辑如下:

  1. 如果当前bean有且仅有一个的构造器,那么直接使用这个构造器创建对象。不管它是有参还是无参。
  2. 如果存在多个构造器,Spring会从中选择一个无参构造器进行创建对象,如果没有无参构造器,那么直接报错。

Spring的设计思想是这样的:

  1. 如果只有一个构造器,那么没有选择,只能使用这个构造器
  2. 如果有多个,只选择没有入参的构造器,因为无参构造方法本身表示了一种默认的意义
  3. 还要一种就是使用了@Autowired注解修饰,那么就表示人工干预 了Spring选择的权利,直接选择程序员指定的构造器,如果有参,里面的参数bean对象(单例)会从单例缓存池中取。
 a.先按照bean类型进行查找,如果只找到一个实例,那么直接注入。
 b.如果找到多个实例,那么会进行匹配入参name名字来确定唯一一个实例。
 c如果没有找到,则会报错,无法创建当前Bean对象

综上所述,Spring会根据Bean的构造器情况进行选择,如果需要人工干预,可以使用@Autowired注解修饰。

AOP的大致流程

在创建对象时,Spring会判断当前对象是否需要进行AOP代理。为了确定当前Bean对象是否需要代理,大致流程如下:

  1. Spring启动时寻找所有使用@AspectJ注解的切面Bean对象
  2. 搜索切面bean的各个方法是否有包含了@Before、@After、@Around注解。
  3. 检查当前Bean或方法是否符合我们编写的Pointcut切面条件。
  4. Spring创建代理对象通常采用cglib代理,JDK代理是另一种模式。后续我们会详细分析此逻辑。

具体流程如下:

  1. 首先当前bean被确认为需要进行代理,将会生成BeanProxy对象,而不是我们构造出来的Bean。
  2. 当前BeanProxy会重写符合切面方法的方法
  3. 当前BeanProxy被依赖注入时,给其他Bean的属性赋值时也会是代理对象。
  4. BeanProxy代理对象都有一个target属性,用于注入被代理对象,即我们正常构造并进行属性注入的Bean对象
  5. 当BeanProxy的切面方法被调用时,首先调用我们编写的切面逻辑,然后调用被代理对象的方法(即我们编写的业务方法)。这里也不太准确,具体得看你写的什么样的切面注解,不过大致都是这样来调用的链路。

Spring事务

一谈到事务,大家首先想到的肯定是@Transaction注解,而这种注解也会被Spring创建对象时检测到,然后会生成代理对象,这种方式其实工作中用到的也特别多,用起来也特别爽,那我们也大概讲下事务的逻辑处理吧,其大致流程如下:

  1. 首先如果当前Bean有@Transaction注解,那么当前bean会成为代理对象。
  2. 当被调用到具体的方法时。Spring则会利用事务管理器TransactionManage获取一个数据库连接。
  3. 直接将当前数据库连接的自动提交关闭,autocommit=false。
  4. 开始执行我们的业务方法,执行业务SQL操作。
  5. 如果执行完方法后,没有异常则提交事务,如果出现异常则进行回滚。

以上是简单的事务处理流程,深入细节会涉及到Spring的事务传播级别,如果现在说的话,会陷入不必要的思考,自此我们的 [Spring入门系列] 也结篇了,在接下来的 [Spring源码系列] 中,我将更加详细地讲解这些内容。

「准备开车,可坐稳了别被摔下来」

先对这些流程有个印象,并带着疑惑来进一步探究Spring的内部机制,好了,今天就讲到这里,我是小雨,我们下期再见。

相关文章
|
5月前
|
XML Java 应用服务中间件
【SpringBoot(一)】Spring的认知、容器功能讲解与自动装配原理的入门,带你熟悉Springboot中基本的注解使用
SpringBoot专栏开篇第一章,讲述认识SpringBoot、Bean容器功能的讲解、自动装配原理的入门,还有其他常用的Springboot注解!如果想要了解SpringBoot,那么就进来看看吧!
650 2
|
10月前
|
人工智能 Java API
Spring AI 实战|Spring AI入门之DeepSeek调用
本文介绍了Spring AI框架如何帮助Java开发者轻松集成和使用大模型API。文章从Spring AI的初探开始,探讨了其核心能力及应用场景,包括手动与自动发起请求、流式响应实现打字机效果,以及兼容不同AI服务(如DeepSeek、通义千问)的方法。同时,还详细讲解了如何在生产环境中添加监控以优化性能和成本管理。通过Spring AI,开发者可以简化大模型调用流程,降低复杂度,为企业智能应用开发提供强大支持。最后,文章展望了Spring AI在未来AI时代的重要作用,鼓励开发者积极拥抱这一技术变革。
3634 71
Spring AI 实战|Spring AI入门之DeepSeek调用
|
11月前
|
安全 Java 数据库
Spring Security 实战指南:从入门到精通
本文详细介绍了Spring Security在Java Web项目中的应用,涵盖登录、权限控制与安全防护等功能。通过Filter Chain过滤器链实现请求拦截与认证授权,核心组件包括AuthenticationProvider和UserDetailsService,负责用户信息加载与密码验证。文章还解析了项目结构,如SecurityConfig配置类、User实体类及自定义登录逻辑,并探讨了Method-Level Security、CSRF防护、Remember-Me等进阶功能。最后总结了Spring Security的核心机制与常见配置,帮助开发者构建健壮的安全系统。
1732 0
|
8月前
|
前端开发 Java API
基于 Spring Boot 3 与 React 的 Java 学生信息管理系统从入门到精通实操指南
本项目基于Spring Boot 3与React 18构建学生信息管理系统,涵盖前后端开发、容器化部署及测试监控,提供完整实操指南与源码,助你掌握Java全栈开发技能。
408 0
|
8月前
|
SQL Java 数据库连接
Spring、SpringMVC 与 MyBatis 核心知识点解析
我梳理的这些内容,涵盖了 Spring、SpringMVC 和 MyBatis 的核心知识点。 在 Spring 中,我了解到 IOC 是控制反转,把对象控制权交容器;DI 是依赖注入,有三种实现方式。Bean 有五种作用域,单例 bean 的线程安全问题及自动装配方式也清晰了。事务基于数据库和 AOP,有失效场景和七种传播行为。AOP 是面向切面编程,动态代理有 JDK 和 CGLIB 两种。 SpringMVC 的 11 步执行流程我烂熟于心,还有那些常用注解的用法。 MyBatis 里,#{} 和 ${} 的区别很关键,获取主键、处理字段与属性名不匹配的方法也掌握了。多表查询、动态
239 0
|
9月前
|
Java 关系型数据库 MySQL
【Spring】【事务】初学者直呼学会了的Spring事务入门
本文深入解析了Spring事务的核心概念与使用方法。Spring事务是一种数据库事务管理机制,通过确保操作的原子性、一致性、隔离性和持久性(ACID),维护数据完整性。文章详细讲解了声明式事务(@Transactional注解)和编程式事务(TransactionTemplate、PlatformTransactionManager)的区别与用法,并探讨了事务传播行为(如REQUIRED、REQUIRES_NEW等)及隔离级别(如READ_COMMITTED、REPEATABLE_READ)。
704 1
|
9月前
|
Java API 微服务
Java 21 与 Spring Boot 3.2 微服务开发从入门到精通实操指南
《Java 21与Spring Boot 3.2微服务开发实践》摘要: 本文基于Java 21和Spring Boot 3.2最新特性,通过完整代码示例展示了微服务开发全流程。主要内容包括:1) 使用Spring Initializr初始化项目,集成Web、JPA、H2等组件;2) 配置虚拟线程支持高并发;3) 采用记录类优化DTO设计;4) 实现JPA Repository与Stream API数据访问;5) 服务层整合虚拟线程异步处理和结构化并发;6) 构建RESTful API并使用Springdoc生成文档。文中特别演示了虚拟线程配置(@Async)和StructuredTaskSco
1030 0
|
11月前
|
存储 安全 Java
Spring Security 入门与详解
Spring Security 是 Spring 框架中的核心安全模块,提供认证、授权及防护功能。本文详解其核心概念,包括认证(Authentication)、授权(Authorization)和过滤器链(Security Filter Chain)。同时,通过代码示例介绍基本配置,如 PasswordEncoder、UserDetailsService 和自定义登录页面等。最后总结常见问题与解决方法,助你快速掌握 Spring Security 的使用与优化。
2713 0
|
存储 安全 Java
Spring Security 入门
Spring Security 是 Spring 框架中的安全模块,提供强大的认证和授权功能,支持防止常见攻击(如 CSRF 和会话固定攻击)。它通过过滤器链拦截请求,核心概念包括认证、授权和自定义过滤器。配置方面,涉及密码加密、用户信息服务、认证提供者及过滤器链设置。示例代码展示了如何配置登录、注销、CSRF防护等。常见问题包括循环重定向、静态资源被拦截和登录失败未返回错误信息,解决方法需确保路径正确和添加错误提示逻辑。
887 2
Spring Security 入门