当前位置: 首页 > news >正文

Spring进阶篇

一、spring复习

1、什么是spring,对spring的认识理解?

        spring是一个轻量级开源的一站式的Java开发框架,目的是为了简化企业级开发。

2、spring的优缺点

优点:轻量级、开源的、简单、IOC(控制反转)和AOP面向切面编程

缺点:配置多,很多都是模板化的配置,管理很多依赖

3、理解IOC和AOP

IOC:控制反转,把项目中创建对象的权力交给Spring框架,由spring框架统一管理项目中的对象,由spring框架生成的对象,称为一个bean对象,spring可以对bean对象进行功能上的增强。

AOP:面向切面编程,使用动态代理的方式,为目标对象提供代理对象,在不修改目标类中的代码时,为目标类添加额外的功能,将额外的功能横切到目标类中。

4、IOC和DI的区别

IOC是一种设计原则,强调控制权的反转,是一种宏观的概念

DI:依赖注入,是实现IOC的具体技术手段,侧重于依赖对象的注入过程。在IOC的基础上把对象注入到我们需要的地方

5、spring注入对象的方式

基于xml配置方式:

属性注入:是使用setter方法来实现

package com.example;public class DataSource {private String url;private String username;private String password;public void setUrl(String url) {this.url = url;}public void setUsername(String username) {this.username = username;}public void setPassword(String password) {this.password = password;}// Getter 方法可按需添加
} 
package com.example;public class UserService {private DataSource dataSource;public void setDataSource(DataSource dataSource) {this.dataSource = dataSource;}// 业务方法public void doSomething() {// 使用 dataSource 进行操作}
}
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsd"><!-- 定义数据源 Bean --><bean id="dataSource" class="com.example.DataSource"><property name="url" value="jdbc:mysql://localhost:3306/test"/><property name="username" value="root"/><property name="password" value="password"/></bean><!-- 定义服务 Bean,注入数据源 --><bean id="userService" class="com.example.UserService"><property name="dataSource" ref="dataSource"/></bean>
</beans>  

构造方法注入:通过构造函数来实现的

package com.example;public class DataSource {private String url;private String username;private String password;public DataSource(String url, String username, String password) {this.url = url;this.username = username;this.password = password;}// Getter 方法可按需添加
}
package com.example;public class UserService {private DataSource dataSource;public UserService(DataSource dataSource) {this.dataSource = dataSource;}// 业务方法public void doSomething() {// 使用 dataSource 进行操作}
} 
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsd"><!-- 定义数据源 Bean --><bean id="dataSource" class="com.example.DataSource"><constructor-arg value="jdbc:mysql://localhost:3306/test"/><constructor-arg value="root"/><constructor-arg value="password"/></bean><!-- 定义服务 Bean,注入数据源 --><bean id="userService" class="com.example.UserService"><constructor-arg ref="dataSource"/></bean>
</beans>

注解方式:

属性注入:是使用@Autowired 注解来实现属性注入

package com.example;import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;@Service
public class UserService {@Autowiredprivate DataSource dataSource;// 业务方法public void doSomething() {// 使用 dataSource 进行操作}
}

构造方法注入:同样可以使用 @Autowired 注解实现构造方法注入

package com.example;import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;@Service
public class UserService {private DataSource dataSource;@Autowiredpublic UserService(DataSource dataSource) {this.dataSource = dataSource;}// 业务方法public void doSomething() {// 使用 dataSource 进行操作}
}

6、自动注入有哪些注解

1、使用spring框架中提供的@Autowired注解,可以添加到要注入的属性上面,或者属性的set方法上,如果直接添加到属性上面,那么set方法可以不需要添加。

默认情况下,要注入的属性对象不能空@Autowired(required=true)

注入时,查找bean的方式有两种:

        1、当只有一个匹配的Bean时默认是通过属性的类型查询

        2、当出现多个匹配的Bean时,需要使用@Qualifier(value=对象ming),或者使用@Primary,Spring 会优先选择被 @Primary 注解标记的 Bean 进行注入。

2、使用jdk中提供的注解@Resource

查找bean也是有两种方式:

1、通过名称查询:会根据字段类型在容器中查找实现了该接口的 Bean

2、如果按类型查找时存在多个匹配的 Bean,@Resource 会抛出 NoUniqueBeanDefinitionException 异常。此时,可以通过指定 name 属性来明确要注入的 Bean。@Resource(name = "adminDao") 通过对象名查询

@Resource和@Autowried的区别?

1、来源不同:@Resource是jdk提供的,@Autowired是spring提供的

2、查找方式不同::@Resource默认按名称( @Component("userDaoImpl"))查找 Bean,@Autowired默认按类型(类名)查找 Bean。

3、支持的属性不同:@Resource(name=Bean的名称,type=Bean的类型),@Autowired(required=true) 表示注入的依赖必须存在,默认是true

import javax.annotation.Resource;
import org.springframework.stereotype.Service;@Service
public class UserService {// 指定名称和类型@Resource(name = "userDaoImpl", type = UserDaoImpl.class)private UserDao userDao;
}
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;@Service
public class UserService {// 依赖可以为 null@Autowired(required = false)private UserDao userDao;
}

4、用法场景不同:@Resource适合明确指定了Bean名称进行注入,其可以保持代码的一致性。

@Autowried:在spring项目中主要依据类型进行注入,并结合@Qulifier注解处理多个匹配Bean的情况,使用其更加方便

7、spring中的bean和new的对象有什么区别?

bean对象是由spring框架创建的,根据我们的配置(事务、日志、统一异常处理),可以进行功能上的增强。

new对象是最原始的对象,没有任何功能的增强。

8、AOP中的术语有哪些,通知有哪些?

连接点:类中可以增强的方法

切入点:类中实际被增强的方法

通知:给切入点添加的功能

目标:被增强的类

代理:代理对象

通知类型:

1、前置通知:@Before,在方法执行前执行

2、后置通知:@After,在方法执行后执行

3、环绕通知:@Around,可以实现前置、后置、返回、异常通知

4、异常通知: @AfterThrowing,在出现异常时执行

5、返回通知:   @AfterReturning,在目标方法正常执行并返回结果后执行,一旦出现异常就不执行

9、spring AOP实现的几种方式

xml配置方式

<!-- 开启 AOP 自动代理 --><aop:aspectj-autoproxy/><!-- 定义目标对象 --><bean id="userService" class="com.example.UserServiceImpl"/><!-- 定义切面 --><bean id="loggingAspect" class="com.example.LoggingAspect"/><!-- 配置 AOP --><aop:config><!-- 定义切入点 --><aop:pointcut id="userServiceMethods" expression="execution(* com.example.UserService.*(..))"/><!-- 定义切面和通知 --><aop:aspect ref="loggingAspect"><!-- 前置通知 --><aop:before method="beforeAdvice" pointcut-ref="userServiceMethods"/><!-- 后置通知 --><aop:after method="afterAdvice" pointcut-ref="userServiceMethods"/></aop:aspect></aop:config>

注解方式

 @Before("execution(* com.example.UserService.*(..))")public void beforeAdvice() {System.out.println("Before method execution");}@After("execution(* com.example.UserService.*(..))")public void afterAdvice() {System.out.println("After method execution");}

10、spring中事务的管理,实现方式有几种,原来是什么?

首先事务是数据库中的特性,在spring中,spring框架对事务开启,提交,回滚进行管理。

编程式事务:通过编写代码来管理事务的开始、提交、回滚,这种方式比较灵活,但代码量比较大,适用于需要精细控制事务边界的场景。

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.TransactionCallback;
import org.springframework.transaction.support.TransactionTemplate;@Service
public class UserServiceImpl implements UserService {@Autowiredprivate JdbcTemplate jdbcTemplate;@Autowiredprivate TransactionTemplate transactionTemplate;@Overridepublic void transferMoney(int fromUserId, int toUserId, double amount) {transactionTemplate.execute(new TransactionCallback<Void>() {@Overridepublic Void doInTransaction(TransactionStatus status) {try {// 扣除转出用户的金额jdbcTemplate.update("UPDATE users SET balance = balance - ? WHERE id = ?", amount, fromUserId);// 模拟异常if (true) {throw new RuntimeException("Simulated exception");}// 增加转入用户的金额jdbcTemplate.update("UPDATE users SET balance = balance + ? WHERE id = ?", amount, toUserId);} catch (Exception e) {status.setRollbackOnly();throw e;}return null;}});}
}    

声明式事务:通过配置文件注解来定义事务的属性,Spring 会自动管理事务的开始、提交和回滚,这种方式代码侵入性小,适用于大多数场景。

    <!-- 配置事务通知 --><tx:advice id="txAdvice" transaction-manager="transactionManager"><tx:attributes><tx:method name="transferMoney" propagation="REQUIRED"/></tx:attributes></tx:advice>
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;@Service
public class UserServiceImpl implements UserService {@Autowiredprivate JdbcTemplate jdbcTemplate;@Transactional@Overridepublic void transferMoney(int fromUserId, int toUserId, double amount) {// 扣除转出用户的金额jdbcTemplate.update("UPDATE users SET balance = balance - ? WHERE id = ?", amount, fromUserId);// 增加转入用户的金额jdbcTemplate.update("UPDATE users SET balance = balance + ? WHERE id = ?", amount, toUserId);}
}

11、声明式事务失效的场景

1、非public方法

2、异常没有抛出

3、数据库不支持事务(myIsam)

4、未指定异常回滚类型:默认情况下,Spring 的声明式事务仅在遇到运行时异常 (RuntimeException)和错误(Error)时回滚,对于受检查异常(如 IOExceptionSQLException 等)则不会回滚。

5、传播行为设置错误。

6、同类方法调用:当一个类中的非事务方法调用同一个类中的事务方法时,事务注解会失效。因为这种调用是通过this引用进行的,而非通过代理对象,所以事务注解不会生效。

7、异步方法调用:若在异步方法中使用事务注解,由于异步方法是在新线程中执行的,事务上下文无法传递,从而导致事务失效

12、springWeb的运行流程

1.用户发送出请求到前端控制器 DispatcherServlet。
2.  DispatcherServlet 收到请求调用 HandlerMapping(处理器映射器)。
3.  HandlerMapping 找到具体的处理器(可查找 xml 配置或注解配置),生成处理器对象及处理器拦截器(如果有),再一起返回给 DispatcherServlet。
4.  DispatcherServlet 调用 HandlerAdapter(处理器适配器)。
5.  HandlerAdapter 经过适配调用具体的处理器(Handler/Controller)。
6.Controller 执行完成向前端响应结果。
 相关组件

DispatcherServlet:前端控制器,不需要程序员开发,由框架提供,在web.xml 中配置。

                作用:统一处理请求和响应,整个流程控制的中心,由它调用其它组件处理用户的请求.
HandlerMapping:处理器映射器,不需要程序员开发)由框架提供。

                作用:根据请求的 url 查找 Handler(处理器/Controller)

HandleAdapter:处理器适配器,不需要程序员开发,由框架提供。

                作用:按照特定规则(HandlerAdapter 要求的规则)去执行 Handler
Handler:处理器,也称之为 Controller,需要程序员去开发

 13、servlet过滤器和spring拦截器

首先过滤器是servlet中规范定义的,拦截器是spring中定义的。

过滤器只可以拦截所有进入到Java后端的请求,拦截器只能拦截进入到处理器(controller,web层)的请求。

14、spring和springboot的关系

springboot是对spring框架的搭建进行了封装,不是代替spring的,底层依然还是spring

15、spring常用的注解

声明Bean的注解

@RestController、@Service、@Repository都可以称为@Component,都是@component的衍生,这些注解在语义上更加明确,能让代码的可读性和可维护性得到提升。

@Component:基本组件

@RestController:控制层

@Service:业务层

@Repository:数据访问层

Bean的声明周期属性

@Scop设置类型:spring容器如何创建新建Bean的实例   @Scop(" ")

singleton:单例,一个spring容器中只有一个Bean的实例,默认的

protetype:每次调用创建一个新的对象

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

注入Bean的注解

@Autowried、出现多个匹配的Bean与@Qualifier配合使用,@Resource

AOP的相关注解

@Aspect:声明一个切面类(包含通知的类)

@After:后置通知

@AfterReturning 返回通知

@Before:在方法执行之前执行

@AfterThrowing 异常通知

@Around:在方法执行之前与之后执行

SpringWeb的常用注解

@RequestMapping: 为类,方法定义访问请求地址@PostMapping:定义只允许 post 请求方式访问地址

@GetMapping:定义只允许 get 请求方式访问地址

@RequestBody:允许 request 的参数在 request 体中以 json 格式传递.

其他注解

@DateTimeFormat:此注解用于属性上,可以方便的把 Date 类型直接转化为我

们想要的格式.

@Transactional 注解放在类级别时,表示所有该类的公共方法都配置相同的事务属性信息。

SpringBoot 注解

@SpringBootApplication:

包含@SpringBootConfiguration、@EnableAutoConfiguration、

@ComponentScan 通常用在主类上;

统一异常处理注解

@RestControllerAdvice,@ExceptionHandler 用于统一异常处理,捕获指定的

异常.

配置类相关注解

@Configuration:声明当前类为配置类

@Bean:注解在方法上,声明当前方法的返回值为一个 bean,替代 xml 中的

方式

Spring 定时器

在启动类上添加 @EnableScheduling

在任务方法上添加 @Scheduled(cron = "*/6 * * * * ?")

16、spring中bean的声明周期

从宏观上来讲,可以分为5个阶段:

1、实例化 Instantiation

2、属性赋值 Populate

3、初始化 Initialization(最关键的,根据各种注解配置,在这里进一步落地实现)

4、将Bean对象放入到容器中使用

5、销毁 Destruction

17、spring中的Bean是线程安全的吗?

spring中的bean如果是单例,始终创建一个对象,所有请求公用一个对象,那么对该单例对象中的成员变量也就只有一份,所有请求共享。

在多用户访问时,可能出现问题,还有种情况,就是像每个请求中,都有属于自己的成员变量使用。所以单例Bean使用时,就有可能出现线程安全问题。

原型Bean每次请求都会创建一个新的对象,不会存在线程安全问题。

单例Bean线程安全问题解决:

        如果成员变量是共享的,多线程操作时,如++等操作,进行加锁控制,如果每一个请求中,都需要一个属于自己的成员变量:

1、单例bean修改为原型bean

2、使用ThreadLocal线程变量,为每一次的请求提供一个变量的副本。

在这里,单例Bean又分为:有状态Bean和无状态Bean

有状态Bean:

        就是有成员变量,而且成员变量可以存储数据,就有可能多线程操作时出现问题。

无状态Bean:

        注入对象,对象不进行数据存储,只是调用方法,每次请求中的参数数据都是相互隔离的

18、Bean的循环依赖

class A{
B b;
}
class B{
A a;
}
public static void main(String[] args){
A a=new A();//创建A对象,关联对象b为null
B b=new B();//创建B对象,关联对象a为null
}
//修然A,B之间相互关联,但是创建对象时,没有任何问题

在spring中存在循环依赖的问题(spring已经解决了)

在spring中我们使用@Autowired注解,那么在创建A对象时,需要关联的B对象要注入,需要去创建B对象,创建B对象时,需要为关联的A注入值,但是此时A对象还没有创建完成,形成了一种死循环。

spring中是如何解决循环依赖的问题?

采用三级缓存来解决循环依赖问题

三级缓存就是三个map(ConcurrentHashMap)对象,来存储不同的对象。

一级缓存:singletonObjiects,一级缓存对象,主要存储创建、初始化完成的bean对象

二级缓存:earlysingletonObjects,二级缓存,主要存储实例化完成,但没有初始化完成的半成品对象。

三级缓存:singletonFactories:主要存储创建对象的工厂对象,创建A对象时还有一个创建A的工厂对象来创建A对象。

过程:

创建A对象时,需要用到B,A创建了一半,把他存储到二级缓存(earlysingletonobiects),把创建A的工厂对象存储到三级缓存中(singletonFactories),把半成品A注入到B中,B完成了创建,存储到一级缓存中(singletonObjects),把B注入到A中,A完成了创建,存储到一级缓存中。

19、spring boot自动装配原理

基本流程:

        springboot启动时,首先对application.yml和pom.xml文件进行读取,获取到项目中使用到的第三方组件,然后读取spring.factories中的spring支持的配置类,最后加载项目中所使用到的组件配置类。

注解层面
启动类:

@SpringBootApplication 注解是一个复合注解 

在@EnableAutoConfiguration 中有一个 @Import({AutoConfigurationImportSelector.class})注解,其中包含AutoConfigurationImportSelector 类.
根据pom.xml中的配置的相关依赖,进行选择性的加载,读取相关依赖的配置类

 

 AutoConfigurationImportSelector 类中关键方法

 ​​​​​​​

 

相关文章:

  • Github 2025-04-26 Rust开源项目日报Top10
  • 自动化测试实战篇
  • SVN 安装指南
  • WebAssembly全栈革命:在Rust与JavaScript之间构建高性能桥梁
  • ARM架构的微控制器总线矩阵
  • k8s学习记录(四):节点亲和性
  • Postman脚本处理各种数据的变量
  • 高级 SQL 技巧:提升数据处理能力的实用方法
  • AutoSAR从概念到实践系列之MCAL篇(二)——Mcu模块配置及代码详解(下)
  • Ollama平替!LM Studio本地大模型调用实战
  • 【那些年踩过的坑】Docker换源加速详细教程(截至2025年4月)
  • 【10分钟读论文】Power Transmission Line Inspections电力视觉水文
  • vue3学习之防抖和节流
  • 二叉搜索树的实现与应用场景
  • 推荐几个免费提取音视频文案的工具(SRT格式、通义千问、飞书妙记、VideoCaptioner、AsrTools)
  • 线性代数(一些别的应该关注的点)
  • GoFly快速开发框架新增UI素材库-帮助开发者快速开发管理后台UI基于ArcoDesign框架开发
  • 深入理解网络安全中的加密技术
  • 月之暗面开源 Kimi-Audio-7B-Instruct,同时支持语音识别和语音生成
  • 中国大陆DNS服务选择指南:阿里云VS AWS,合规性与最佳实践
  • 俄联邦安全局:俄军高级官员汽车爆炸案嫌疑人已被捕
  • 最高法改判一起植物新品种侵权案:判赔逾5300万元破纪录
  • 弘扬 “上海精神”,上合组织政党论坛聚焦政党责任与使命
  • 三亚一景区发生游客溺亡事件,官方通报:排除他杀
  • 【社论】以“法治之盾”护航每一份创新
  • 财政部、证监会:加强对会计师事务所从事证券服务业务的全流程监管