Spring 知识点
Spring
Spring 是什么?
- Spring为了解决企业级应用的复杂性而创建,简化开发。
- 如下简化:
- 基于
POJO
的轻量级和最小侵入性编程; - 以
IoC(控制反转)、DI(依赖注入)
和面向接口实现松耦合; - 基于AOP(切面编程)和惯性进行声明式编程;
- 以切面和模版减少样式代码;
- 基于
Spring IoC(控制反转)
IoC 负责创建、维护、并管理对象之间依赖关系的容器。
什么叫控制反转:控制权的转移——应用程序本身负责依赖对象的创建和维护的控制权转移给
IoC
容器管理。什么控制被反转:获取依赖对象的过程被反转了——获取依赖对象的过程由自身变为
IoC
容器主动注入。为什么要使用IoC:实现对象之间的解耦、复用;
实现方式:DI(依赖注入)、工厂模式。
Spring DI(依赖注入)
什么叫依赖注入:程序在运行时依赖IOC容器来动态注入对象所需的资源;(Java DI官方标准是JSR-330,Guice是一个轻量级的DI框架。)
DI是IoC的一种实现方式。
为什么使用DI:松耦合、易测试、强内聚、可重用。
方式一:Field 注入
@Autowired
private OrderWorkApplicationService orderWorkApplicationService;
- 方式二:Setter 方法注入
public class OrderWorkApi {
private OrderWorkApplicationService orderWorkApplicationService;
@Autowired
public void setOrderWorkApplicationService(OrderWorkApplicationService orderWorkApplicationService){
this.orderWorkApplicationService = orderWorkApplicationService;
}
}
- 方式二:Constructor 注入
public class OrderWorkApi {
private final OrderWorkApplicationService orderWorkApplicationService;
public OrderWorkApi(final OrderWorkApplicationService orderWorkApplicationService){
this.orderWorkApplicationService = orderWorkApplicationService;
}
}
- 方式三:Lombok + Constructor 注入
- 保证依赖的对象不为Null。
- 避免 Field 注入的循环依赖问题。
@RequiredArgsConstructor
public class OrderWorkApi {
private final OrderWorkApplicationService orderWorkApplicationService;
}
Spring AOP(切面编程)
- 什么是AOP:通过“
预编译
”或“运行期动态代理
”以垂直维护实现程序功能的一种技术。 - 用途:提供了声明式的企业服务、替代了
EJB
的服务声明,允许自定义,以完成OOP(面向对象编程)
与AOP
的互补使用。 - 实现:不是为了提供最完整的AOP实现、而是侧重于提供一种AOP实现与Spring IoC容器之间的整合,用于解决常见的问题(日志、事务、异常)。
- 预编译:AspectJ
- 运行期动态代理(jdk动态代理、CGLib动态代理):Spring AOP、Jboss AOP
- 区别:CGLib动态代理无接口、jdk动态代理有接口。
- 例子
package com.gdbyway.bpg.ip.nis.aop;
import com.gdbyway.bpg.ip.nis.annotations.TestSoul;
import com.gdbyway.bpg.ip.nis.application.service.diagnosis.DiagnosisApplicationService;
import com.gdbyway.bpg.ip.nis.types.diagnosis.representation.PatHistoryDiagRepresentation;
import com.gdbyway.bpg.ip.nis.types.discharge.query.CommonPatHistoryDiagQuery;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.*;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import java.util.List;
@Aspect
@Configuration
public class TestSoulAspect {
@Autowired
private DiagnosisApplicationService applicationService;
//对使用@TestSoul注解作为切入点
@Pointcut("@annotation(com.gdbyway.bpg.ip.nis.annotations.TestSoul)")
public void pointcut() {
}
//对使用@TestSoul注解作为切入点
@Before("pointcut()")
public void before(JoinPoint joinPoint) {
TestSoul testSoul = ((MethodSignature) joinPoint.getSignature()).getMethod().getAnnotation(TestSoul.class);
System.out.println("----------------------myAsp-------------------------------------------------");
CommonPatHistoryDiagQuery query = new CommonPatHistoryDiagQuery();
query.setPatId("96187");
List<PatHistoryDiagRepresentation> ss = applicationService.findByPatId(query);
System.out.println(ss);
}
//返回时处理
@AfterReturning(value = "pointcut()")
public void afterReturning() {
}
//异常时处理
@AfterThrowing(pointcut = "pointcut()",throwing = "ex")
public void afterThrowing(JoinPoint joinPoint, Throwable ex) {
}
}
Spring MVC
- 什么是MVC: 一种架构模式、思考方式——程序分层、分工合作、既相互独立又协同工作。
- M(模型层):展示信息
- V(视图层):界面布局
- C(控制层):处理业务逻辑
Spring @Async(异步)
@Async
可标记在方法上,以便异步调用该方法。调用者将在调用时立即返回,方法的实际执行将提交给SringTaskExecutor的任务中,由指定的线程池中的线程执行!实际应用中:推荐使用自定义线程池模式(自定义线程池常用方案:重新实现接口AsyncConfigurer)
应用场景
同步
:整个操作流程依次执行,每个过程执行完毕、并返回结果!异步
:异步调用只是发送调用的指令,调用者无需等待被调用的方法完全执行完毕,而是继续执行之后的流程!注意:Java一般基于创建独立的线程完相应的异步调用逻辑,通过主线程和业务子线程之间执行流程,从而在启动独立的线程之后,主线程继续执行而不会产生停滞等待的情况。
Spring 的线程池
SimpleAsyncTaskExecutor
:默认每次调用都创建新的线程,不重用线程、并非真正的线程池!SyncTaskExecutor
:同步操作,没有实现异步调用,适用于不需要多线程的地方!ConcurrentTaskExecutor
:ThreadPoolTaskExecutor
不被满足时,可以考虑使用!SimpleThreadPoolTaskExecutor:
线程池同时被Quartz和非Quartz使用,才需要使用此类!ThreadPoolTaskExecutor:
最常用。
@Async默认:SimpleAsyncTaskExecutor
自定义线程池方式
- 实现接口AsyncConfigurer
- 继承AsyncConfigurerSupport
- 配置自定义的TaskExecutor
Spring @Transactional(事务)
Spring提供了两种事务管理机制:
编程式事务
和声明式事务
。编程式事务:是指在代码中手动的管理事务的提交、回滚等操作,代码侵入性比较强。
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.DefaultTransactionDefinition;
public class MyService {
private final JdbcTemplate jdbcTemplate;
private final PlatformTransactionManager transactionManager;
@Autowired
public MyService(JdbcTemplate jdbcTemplate, PlatformTransactionManager transactionManager) {
this.jdbcTemplate = jdbcTemplate;
this.transactionManager = transactionManager;
}
public void performTransactionalOperation() {
DefaultTransactionDefinition def = new DefaultTransactionDefinition();
TransactionStatus status = transactionManager.getTransaction(def);
try {
// 执行数据库操作,例如:
jdbcTemplate.update("INSERT INTO my_table (name) VALUES ('John Doe')");
jdbcTemplate.update("UPDATE another_table SET count = count + 1 WHERE id = ?", 1);
// 如果没有异常,提交事务
transactionManager.commit(status);
} catch (Exception ex) {
// 如果发生异常,回滚事务
transactionManager.rollback(status);
throw ex; // 可以选择重新抛出异常或进行其他处理
}
}
}
- 声明式事务:基于
AOP
面向切面使业务和事务解耦,代码侵入性比较低。
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 MyService {
private final JdbcTemplate jdbcTemplate;
@Autowired
public MyService(JdbcTemplate jdbcTemplate) {
this.jdbcTemplate = jdbcTemplate;
}
@Transactional(rollbackFor = Exception.class)
public void performTransactionalOperation() {
// 执行数据库操作,例如:
jdbcTemplate.update("INSERT INTO my_table (name) VALUES ('John Doe')");
jdbcTemplate.update("UPDATE another_table SET count = count + 1 WHERE id = ?", 1);
// 如果以上操作成功,事务将自动提交;如果发生异常,事务将自动回滚
// 也可以手动设置回滚
// TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
}
}
常见@Transactional声明式事务的失效场景
事务方法内部捕捉了异常,但没有抛出:如果事务方法内部捕获了异常且没有重新抛出,那么Spring事务管理器不会感知到异常,因此不会触发事务回滚。为了确保事务能够正常回滚,应该让异常冒泡到方法外部。
同一个类中方法调用/this调用:如果在一个类中,一个方法调用了同一个类的另一个被
@Transactional
注解的方法,那么被调用的方法的事务注解将不会生效。这是因为 Spring 的 AOP 代理通常只会在不同类的方法调用时生效。this
引用的是当前类的实例,而不是 Spring 代理的实例,因此事务增强不会应用。如下为其中一种解决方案:import org.springframework.aop.framework.AopContext;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional; //
@Service
@EnableAspectJAutoProxy(exposeProxy = true)
public class MyService { private final JdbcTemplate jdbcTemplate; @Autowired
public MyService(JdbcTemplate jdbcTemplate) {
this.jdbcTemplate = jdbcTemplate;
} // 改为动态代理调用,而非直接调用
public void insertBusiness(){
MyService impl = (MyService) AopContext.currentProxy();
impl.insert();
} @Transactional(rollbackFor = Exception.class)
public void insert(){
jdbcTemplate.update("INSERT INTO my_table (name) VALUES ('John Doe')");
jdbcTemplate.update("UPDATE another_table SET count = count + 1 WHERE id = ?", 1);
}
}
方法可见性:如果
@Transactional
注解被应用于一个非public
方法(如protected
、private
或默认包可见性),虽然不会报错,但事务设置将不会起作用。@Transactional
注解应该只应用于public
方法,因为 Spring AOP 代理通常是通过代理对象来调用目标方法的,而代理对象只能调用public
方法。数据库引擎不支持事务:如果使用的数据库引擎不支持事务(例如,MyISAM 存储引擎在 MySQL 中不支持事务),那么即使使用了
@Transactional
注解,事务也不会生效。异常类型:Spring 默认只会对运行时异常(
RuntimeException
及其子类)进行事务回滚。如果方法抛出了检查异常(即非运行时异常),并且没有被捕获处理,事务也不会回滚。可以通过在@Transactional
注解中设置rollbackFor
属性来指定需要回滚的异常类型。事务传播行为设置不当:
@Transactional
注解中的propagation
属性用于设置事务的传播行为。如果传播行为设置不当,可能会导致事务不按照预期工作。例如,TransactionDefinition.PROPAGATION_NEVER
表示以非事务方式运行,如果当前存在事务,则抛出异常。
获取Spring Bean
- 特殊场景获取Bean方式(定时任务):
ApplicationContextAware
@Component
public class ApplicationServiceFactory implements ApplicationContextAware {
private static ApplicationContext applicationContext;
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
ApplicationServiceFactory.applicationContext = applicationContext;
}
public static <T> T getBean(Class<T> clazz) {
if (Objects.isNull(applicationContext)) {
throw new NullPointerException("Spring ApplicationContext is Null");
}
return applicationContext.getBean(clazz);
}
public static ApplicationContext getApplicationContext(){
return applicationContext;
}
}
获取接口的所有实现类
- InitializingBean
@Component
public class ApplicationServiceFactory implements InitializingBean {
@Override
public void afterPropertiesSet() {
}
}
Spring 知识点的更多相关文章
- Spring知识点回顾(08)spring aware
Spring知识点回顾(08)spring aware BeanNameAware 获得容器中的bean名称 BeanFactoryAware 获得当前的bean factory Applicatio ...
- Spring知识点回顾(07)事件发布和监听
Spring知识点回顾(07)事件发布和监听 1.DemoEvent extends ApplicationEvent { public DemoEvent(Object source, String ...
- Spring知识点回顾(01)Java Config
Spring知识点回顾(01) 一.Java Config 1.服务和服务注入 2.Java 注解 :功能更强一些 3.测试验证 二.注解注入 1.服务和服务注入 2.配置加载 3.测试验证 三.总结 ...
- Spring知识点复习
Spring知识点复习 一.专业术语 侵入式设计 引入框架,对现有的类的结构有影响,即需要实现或继承某些特定类.如:Struts框架 非侵入式设计 引入框架,对现有的类结构没有影响.如:Hiberna ...
- <转>Spring 知识点提炼
Spring 知识点提炼 1. Spring框架的作用 轻量:Spring是轻量级的,基本的版本大小为2MB 控制反转:Spring通过控制反转实现了松散耦合,对象们给出它们的依赖,而不是创建或查找依 ...
- Spring知识点总结(三)之注解方式实现IOC和DI
1. 注解概念 所谓注解就是给程序看的提示信息,很多时候都用来作为轻量级配置的方式. 关于注解的知识点,参看java基础课程中java基础加强部分的内容. 2 ...
- Spring知识点提炼
原文出处: 朱小厮 1. Spring框架的作用 轻量:Spring是轻量级的,基本的版本大小为2MB 控制反转:Spring通过控制反转实现了松散耦合,对象们给出它们的依赖,而不是创建或查找依赖的对 ...
- Spring知识点总结大全(2)
3.Spring的AOP 一.AOP(Aspect-oriented programming,面向切面编程): 什么是AOP? 定义:将程序中的交叉业务逻辑提取出来,称之为切面.将这些切面动态织入到目 ...
- Spring知识点总结大全(1)
1.Spring的分层结构 1.Presentation layer(表示层) (1) 表示逻辑(生成界面代码) (2) 接收请求 (3) 处理业务层抛出的异常 (4) 负责规则验证(数据格式,数据非 ...
- Spring知识点总结
1.1 什么是Spring Spring是分层的JavaSE/EE full-stack(一站式)轻量级开源框架,以IoC(Inverse of Control 反转控制)和AOP(Aspect Or ...
随机推荐
- 全套解决方案:中文NLP训练框架,支持大模型训练和文本生成,快速上手,海量训练数据!
全套解决方案:基于pytorch.transformers的中文NLP训练框架,支持大模型训练和文本生成,快速上手,海量训练数据! 1.简介 目标:基于pytorch.transformers做中文领 ...
- 20.5 OpenSSL 套接字RSA加密传输
RSA算法同样可以用于加密传输,但此类加密算法虽然非常安全,但通常不会用于大量的数据传输,这是因为RSA算法加解密过程涉及大量的数学运算,尤其是模幂运算(即计算大数的幂模运算),这些运算对于计算机而言 ...
- 面试官:SpringCloudGateway过滤器类型有哪些?
在 Spring Cloud Gateway 中,过滤器是在请求到达目标服务之前或之后,执行某些特定操作的一种机制.例如,它可以实现对传入的请求进行验证.修改.日志记录.身份验证.流量控制等各种功能. ...
- mybatis批量插入支持默认值和自定义id生成策略的免写sql插件
最近做项目时用了免写sql的插件但是发现批量操作不满足现有需求.所以,在原有基础之上扩展了批量的操作支持[支持插入默认值和自定义id生成策略].使用方法如下: 一:在pom文件中引入jar配置 < ...
- STM8 bootloader 升级方案程序设计(一)
1.前言 上一篇单片机 IAP 功能基础开发篇之APP升级(一)讲到了单片机 IAP 功能给 APP 程序升级的设计思路,这篇介绍的是具体实现方式. 这篇介绍关于 STM8 系列实现 bootload ...
- Linux如何禁用透明大页
环境: RHEL 6.5 + Oracle 11.2.0.4 RAC 1.确认透明大页是否开启 grep HugePage /proc/meminfo cat /sys/kernel/mm/redha ...
- Nodepad++格式化XML和JSON字符串
(一)格式化XML 1.安装XML Tools 在notepad++中点击菜单栏[插件]-[插件管理]. 在插件管理界面选择[XML Tools],点击[安装]. 2.打开XML文件 在notepad ...
- 听说有 Hugging Face 陪伴的春节,是这样的…
辞旧迎新春节到,家家户户好热闹.Hugging Face 中国团队成员祝各位社区成员们新春快乐,万事如意! 过去的一年我们持续看到 AI 技术的腾飞和发展,以及诸多机构为开源 AI 作出巨大的贡献.非 ...
- C语言程序设计之字符串处理
C语言程序设计-字符串处理 第一题:回文数判断 问题描述] 回文是正读和倒读都一样的句子.读入一个最大长度不超过50个字符的句子,判断其是否是回文. [输入形式] 输入一个最大长度不超过50个字符的句 ...
- jq 完成复选框的全选和全不选,并组装成数组发送到后台
jQuery 代码实现,HTML dom节点对应js的id 即可 <script> $(function() { //复选框全选和全不选 $("#selectAll") ...