Spring

本文详细介绍了Spring框架的核心概念,包括IoC容器与依赖注入、AOP面向切面编程及其在事务管理中的应用,SpringBean的声明与管理,以及SpringMVC和SpringBoot中的自动装配和设计模式。
摘要由CSDN通过智能技术生成

目录

Spring

什么是Spring框架?

Spring IoC

IoC解决了什么问题?

IoC和DI有区别吗?

Spring AOP

什么是AOP?

AOP为什么叫面向切面编程?

AOP解决了什么问题?

多个切面的执行顺序如何控制?

Spring Bean的管理

什么是Spring Bean?

将一个类声明Bean的注解有哪些?

@Component和@Bean的区别

@Autowired和@Resource的区别

Bean的作用域

Bean是线程安全的吗?

解决办法

Bean生命周期

BeanFactory 和 ApplicationContext

循环依赖

Spring中解决循环依赖问题

Spring事务

什么是事务?

事务的特性(ACID)

Spring支持两种方式的事务管理

Spring事务管理接口

事务传播行为

事务回滚规则

@Transactional注解

常用参数​编辑

注意事项

Spring框架中用了哪些设计模式

SpringMVC

SpringMVC的核心组件

工作原理​编辑

SpringBoot

SpringBoot自动装配原理

什么是自动装配?

SpringBoot是如何实现自动装配

@EnableAutoConfiguration实现自动装配的核心注解

AutoConfigurationImportSelector加载自动装配类

Servlet的过滤器与 Spring 拦截器区别​编辑

Spring常用注解


Spring

什么是Spring框架?

Spring是一个轻量级的(核心包),非侵入式的一站式(数据持久层、web层、IoC、AOP)的框架,为了简化企业级开发,开箱即用

轻量级:指的是核心jar包小

非侵入式:框架代码不会侵入到业务代码,业务代码不会实现或继承框架中接口或类

核心:IoC(控制反转)、AOP(面向切面编程)

Spring IoC

IoC(Inversion of Control:控制反转)是一种设计思想,将原本在程序中手动创建对象的控制权交给Spring框架去管理

IoC解决了什么问题?

  • 对象之间的依赖程度降低了

  • 资源变得容易管理

例如:我们要在Service层使用Dao层,但是Dao接口下有多个实现类,如果没有IoC的话我们就要new多个对象才能实现我们的业务,而且要是如果只有一个类引用了Dao还好,如果是多个,那我们就要一个一个去改,增加了很多没必要的工作量

但是有了IoC,我们在使用的时候直接向容器要就行

IoC和DI有区别吗?

IoC最常见以及最合理的实现方式叫做依赖注入(Dependency Injection,简称 DI)

Spring AOP

什么是AOP?

AOP即面向切面编程,面向对象的延续,二者互补

AOP的目的是将横切关注点(如日志记录、事务管理、权限控制等)从核心业务逻辑中分离出来,通过动态代理等技术,实现代码的复用和解耦,提高代码可维护性和扩展性。

简单来说就是通过一个代理对象,在不修改原来代码的情况下对目标类增强

AOP为什么叫面向切面编程?

核心思想是从将横切关注点从核心业务中分离出来,形成一个个切面(Aspect)

  • 横切关注点:多个类对象中的公共行为(如日志、事务、权限)

  • 切面:对横切关注点封装的类

  • 连接点:方法执行的某个特定时刻(如方法调用、异常抛出)

  • 通知:切面在某个连接点要执行的操作,有五种类型

    • 前置通知(Before)

    • 后置通知(After)

    • 返回通知(AfterReturning)

    • 异常通知(AfterThrowing)

    • 环绕通知(Around)

  • 切点:一个切点是一个表达式,匹配哪些连接点需要被增强,比如比如 execution(* com.zl.service..*(..))匹配 com.zl.service 包及其子包下的类或接口。

  • 织入:将通知应用到切点匹配的连接点上。一般分为编译期织入(AspectJ)和运行期织入(AspectJ)

AOP解决了什么问题?

如果没有AOP,我们在写例如日志管理、事务管理、权限控制等功能时,就要把一份一模一样的代码复制粘贴在每一个需要的业务模块,这样代码显得很冗余,也不好管理,改一处就要改很多处

但是有了AOP,我们将这种公共功能封装到一个类中,哪里需要直接用就行,修改的时候,只用修改封装的那个类的东西即可,大大减轻我们的工作量,我们的代码也更加优雅

多个切面的执行顺序如何控制?

@Order(3)注解可以解决,值越小优先级越高

Spring Bean的管理

什么是Spring Bean?

Bean指的就是IoC容器管理的对象

我们需要告诉IoC帮助我们管理哪些对象,可以用XM文件、注解来实现

<bean id="admin" class="com.zl.spring.model.Admin">
    <constructor-arg  name="id" value="100"></constructor-arg>
    <constructor-arg  name="account" value="admin"></constructor-arg>
</bean>

将一个类声明Bean的注解有哪些?

  • @Component:通用注解,如果一个Bean不知道哪一层,可以使用此注解

  • @Repository : 对应持久层(Dao层)注解,主要用于数据库操作

  • @Service :对应服务层,主要设计一些复杂逻辑

  • @Service : 对应SpringMVC控制层,用于接收用户请求并调用Service层数据返回给前端

@Component和@Bean的区别

  • @Component 注解作用于类,而@Bean注解作用于方法。

  • @Component 通常是通过类路径扫描自动侦测以及自动装配到Spring容器中,而@Bean告诉Spring这是某个类实例,当我需要的时候给我

  • @Bean 注解比 @Component 注解的自定义性更强,

@Autowired和@Resource的区别

  • @Autowired 是 Spring 提供的注解,@Resource 是 JDK 提供的注解

  • Autowired 默认的注入方式为byType(根据类型进行匹配),@Resource默认注入方式为 byName(根据名称进行匹配)。

  • Autowired 可以通过 @Qualifier 注解来显式指定名称,@Resource可以通过 name 属性来显式指定名称。

  • @Autowired 支持在构造函数、方法、字段和参数上使用。@Resource 主要用于字段和方法上的注入,不支持在构造函数或参数上使用。

Bean的作用域

  • singleton : IoC 容器中只有唯一的 bean 实例。Spring 中的 bean 默认都是单例的,是对单例设计模式的应用。

  • prototype : 每次获取都会创建一个新的 bean 实例。也就是说,连续 getBean() 两次,得到的是不同的 Bean 实例。

Bean是线程安全的吗?

Bean是否是线程安全的,取决于其作用域和状态

  • prototype作用域下,每次都会创建一个新的bean实例,不存在资源竞争,所以不存在线程安全问题

  • singleton作用域下,IoC中只有唯一的bean实例,可能会存在资源竞争(有状态才会存在),不过这个取决于Bean是否有状态,大部分下是无状态的

    • 无状态:不会存储数据,例如Dao、Service、Controller,这些只关注方法调用本身

    • 有状态:是有数据存储功能(例如包含成员变量)

解决办法
  1. 在Bean中尽量避免可变的成员变量

  2. 利用ThreadLocal,将可变的成员变量保存在其中

Bean生命周期

生命周期

何时生

1. 实例化 Instantiation 通过反射机制以及工厂创建出来的原始对象
2. 属性赋值 Populate
3. 初始化 Initialization(完成对原始对象的各种功能增强AOP生成代理对象),完成后就把bean对象放入到容器中使用
4. 销毁 Destruction
<bean id="" class="" scope="" destory-method="" init-method="" lazy-init="true"></bean>

何时销毁

BeanFactory 和 ApplicationContext

两者都是接口

  • BeanFactory:延迟注入(使用到某个 bean 的时候才会注入),相比于ApplicationContext 来说会占用更少的内存,程序启动速度更快。

  • ApplicationContext:容器启动的时候,不管你用没用到,一次性创建所有 bean 。BeanFactory 仅提供了最基本的依赖注入支持,ApplicationContext 扩展了 BeanFactory ,除了有BeanFactory的功能还有额外更多功能,所以一般开发人员使用ApplicationContext会更多。

循环依赖

两个类之间相互关联(依赖)

A类中关联B类

B类中关联A类

这个在自己new对象时,没有任何问题,只需要给关联的对象赋值为null

但是在Spring中就有问题

在Spring管理的bean时,在自动注入时,如果两个类相互之间关联,那么会出现注入时,另一个对象还没有初始化完成

Spring中解决循环依赖问题

通过三级缓存(就是三个Map对象)

一级缓存(singletonObjects):主要存储初始化完成的对象

二级缓存(earlySingletonObjects):存储实例化完成的半成品bean对象,提前暴露给需要的地方

三级缓存(singletonFactories):放的是创建对象的工厂

当A需要B时,那么先从一级缓存中找B,没有,然后到二级缓存中找到B,

也没有,就去三级缓存中,找到B对应的工厂,创建出B对象(原始对象,半成品)

把B对象放到了二级缓存中

Spring事务

Spring事务管理,指的是spring框架提供了对事务进行提交,回滚功能,帮助我们进行事务管理

什么是事务?

事务是逻辑上一组操作,要么都执行,要么都不执行

事务的特性(ACID)

  • 原子性(Atomicity):事务最小的执行单位,保证动作要么全部完成,要么都不完成

  • 一致性(Consistency):执行任务前后,数据保持一致

  • 隔离性(Isolation):并发访问数据库,一个用户的事务不被其他事务干扰

  • 持久性(Durability):一个事务被提交后,对数据库数据的改变是持久的

Spring支持两种方式的事务管理

  • 编程式事务管理:通过 TransactionTemplate或者TransactionManager手动管理事务,较少用到

  • 声明式事务管理:使用 @Transactional注解进行事务管理,实际是通过AOP实现的

Spring事务管理接口

  • PlatformTransactionManager:(平台)事务管理器,Spring 事务策略的核心,Spring 并不直接管理事务,而是提供了多种事务管理器,通过这个接口,Spring为很多平台提供了对应的事务管理器,例如JDBC

  • TransactionDefinition:事务定义信息(事务隔离级别、传播行为、超时、只读、回滚规则)。

  • TransactionStatus:事务运行状态。例如是否是新的事务、是否为只回滚,设置为只回滚、是否已完成

事务传播行为

是为了解决业务层方法之间互相调用的事务问题

若是错误的配置以下3种传播行为,事务将不会回滚,使用的很少:

  • TransactionDefinition.PROPAGATION_SUPPORTS

  • TransactionDefinition.PROPAGATION_NOT_SUPPORTED

  • TransactionDefinition.PROPAGATION_NEVER

事务回滚规则

默认情况下,事务只有遇到运行期异常(RuntimeException 的子类)时才会回滚,Error 也会导致事务回滚,但是,在遇到检查型(Checked)异常时不会回滚。

@Transactional注解

可作用在方法、类中

常用参数
注意事项
  • @Transactional 注解只有作用到 public 方法上事务才生效,不推荐在接口上使用;

  • @Transactional 注解的方法所在的类必须被 Spring 管理,否则不生效;

  • 底层数据库引擎必须支持事务,否则不生效

  • 正确的设置 @TransactionalrollbackForpropagation 属性,否则事务可能会回滚失败,例如rollbackFor = Exception.class任何异常都不提交事务

Spring框架中用了哪些设计模式

  • 工程设计模式:Spring使用工厂模式通过BeanFactoryApplicationContext 创建 bean 对象。

  • 代理设计模式:Spring AOP功能的实现

  • 单例设计模式:Spring中的Bean默认是单例的

  • 模板方法模式: Spring 中 jdbcTemplatehibernateTemplate 等以 Template 结尾的对数据库操作的类,它们就使用到了模板模式。

SpringMVC

MVC 是模型(Model)、视图(View)、控制器(Controller)的简写,其核心思想是通过将业务逻辑、数据、显示分离来组织代码。

SpringMVC一般把后端项目分为Service 层(处理业务)、Dao 层(数据库操作)、Entity 层(实体类)、Controller 层(控制层,返回数据给前台页面)。

SpringMVC的核心组件

  • DispatcherServlet核心的中央处理器,负责接收请求、分发,并给予客户端响应。

  • HandlerMapping处理器映射器,根据 URL 去匹配查找能处理的 Handler ,并会将请求涉及到的拦截器和 Handler 一起封装。

  • HandlerAdapter处理器适配器,根据 HandlerMapping 找到的 Handler ,适配执行对应的 Handler

  • Handler请求处理器,处理实际请求的处理器。

  • ViewResolver视图解析器,根据 Handler 返回的逻辑视图 / 视图,解析并渲染真正的视图,并传递给 DispatcherServlet 响应客户端

工作原理

客户端发送请求,到达DispatcherServlet,根据请求信息调用HandlerMapping,根据URL去匹配查询能处理的Handler(也就是Controller),并将请求涉及到的拦截器和 Handler一起封装,DispatcherServlet调用HandlerAdapter适配器执行HandlerHandler完成用户请求处理后,会返回一个ModelAndView

SpringBoot

开发基于Spring,是在Spring的基础上简化配置文件,真正做到开箱即用,生态好,让程序员只用专注于业务代码上而不是各种配置

SpringBoot自动装配原理

什么是自动装配?

简单理解,就是通过注解或者一些简单的配置就能在SpringBoot的帮助下实现某些功能

SpringBoot是如何实现自动装配

我们先看下SpringBoot的核心注解@SpringBootApplication

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan(
    excludeFilters = {@Filter(
    type = FilterType.CUSTOM,
    classes = {TypeExcludeFilter.class}
), @Filter(
    type = FilterType.CUSTOM,
    classes = {AutoConfigurationExcludeFilter.class}
)}
)
public @interface SpringBootApplication {}
-----------------------分割线-----------------------------------
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Configuration
@Indexed
public @interface SpringBootConfiguration {}

由此源码可以看出@SpringBootApplication是由@Configuration@EnableAutoConfiguration@ComponentScan 注解的集合

  • @EnableAutoConfiguration:启用 SpringBoot 的自动配置机制

  • @Configuration:允许在上下文中注册额外的 bean 或导入其他配置类

  • @ComponentScan:扫描被@Component (@Service,@Controller)注解的 bean,注解默认会扫描启动类所在的包下所有的类 ,可以自定义不扫描某些 bean。

@EnableAutoConfiguration实现自动装配的核心注解

EnableAutoConfiguration 只是一个简单地注解,自动装配核心功能的实现实际是通过 AutoConfigurationImportSelector类。

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@AutoConfigurationPackage//将main包下的所有组件注册到容器中
@Import({AutoConfigurationImportSelector.class})// 加载自动装配类
public @interface EnableAutoConfiguration {
    String ENABLED_OVERRIDE_PROPERTY = "spring.boot.enableautoconfiguration";
​
    Class<?>[] exclude() default {};
​
    String[] excludeName() default {};
}
AutoConfigurationImportSelector加载自动装配类
public class AutoConfigurationImportSelector implements DeferredImportSelector, BeanClassLoaderAware, ResourceLoaderAware, BeanFactoryAware, EnvironmentAware, Ordered {}
​
public interface DeferredImportSelector extends ImportSelector {}
​
public interface ImportSelector {
    String[] selectImports(AnnotationMetadata importingClassMetadata);
}

由以上源码可以看出,AutoConfigurationImportSelector实现了ImportSelector接口,这个接口中的selectImports方法主要用于获取所有符合条件的类的全限定类型,被加载到IoC容器中

private static final String[] NO_IMPORTS = new String[0];
​
public String[] selectImports(AnnotationMetadata annotationMetadata) {
        // <1>.判断自动装配开关是否打开
        if (!this.isEnabled(annotationMetadata)) {
            return NO_IMPORTS;
        } else {
          //<2>.获取所有需要装配的bean
            AutoConfigurationMetadata autoConfigurationMetadata = AutoConfigurationMetadataLoader.loadMetadata(this.beanClassLoader);
            AutoConfigurationImportSelector.AutoConfigurationEntry autoConfigurationEntry = this.getAutoConfigurationEntry(autoConfigurationMetadata, annotationMetadata);
            return StringUtils.toStringArray(autoConfigurationEntry.getConfigurations());
        }
    }

这里的getAutoConfigurationEntry()方法负责加载自动配置类

由此可见,自动装配是先进行判断是否开启自动装配,然后去获取需要自动装配的配置类,读取META-INF/spring.factories,但是并不是里面所有的配置类都会加载,在这其中会进行过滤,我们pom.xml文件中有的依赖它会留下,没有的会过滤掉

Servlet的过滤器与 Spring 拦截器区别

  • 过滤器通常在进入Servlet前后就会触发,而拦截器是在请求进入Controller前后可以触发

  • 拦截器只对Controller层请求有作用,过滤器对所有请求都起作用,包括静态资源

  • 拦截器基于Java反射机制实现,不依赖Servlet容器,可以在Java任何地方使用,过滤器基于函数回调机制,依赖Servlet容器的生命周期

  • 由于拦截器能够更精细地控制业务流程,它通常用于登录验证、权限检查、日志记录等业务相关的增强处理。过滤器则更多用于通用的功能,如字符编码过滤、安全过滤、性能监控等。

Spring常用注解

声明 bean 的注解

@Component:泛指各种组件

@Controller、@Service、@Repository 都可以称为@Component

@Controller:控制层

@Service:业务层

@Repository:数据访问层

Bean 的生命周期属性

@Scope 设置类型包括:设置 Spring 容器如何新建 Bean 实例

singleton:单例,一个 Spring 容器中只有一个 bean 实例,默认模式

protetype:每次调用新建一个 bean

request:web 项目中,给每个 http request 新建一个 bean

session:web 项目中,给每个 http session 新建一个 bean

globalSession:给每一个 global http session 新建一个 Bean 实例

SpringMVC 常用注解

@RestController : 该 注 解 为 一 个 组 合 注 解 , 相 当 于 @Controller 和@ResponseBody 的组合,注解在类上,意味着,该 Controller 的所有方法都默认加上了@ResponseBody。

@RequestMapping:用于映射 web 请求,包括访问路径和参数

@ResponseBody:支持将返回值放到 response 内,而不是一个页面,通常用户返回 json 数据

@RequestBody:允许 request 的参数在 request 体中,而不是在直接连接的地址后面

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

重开之Java程序员

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值