Lazy loaded image
技术分享
SpringBoot核心
00 min
2023-9-1
2024-11-25
type
status
date
slug
summary
tags
category
icon
password

Spring 基础

IOC(Inversion of Control)

notion image
  • Core:使用了 IoC 设计思想提供了 DI 功能
  • Beans(org.springframework.beans):BeanFactory 接口,提供配置机制,可以管理任何类型的对象
  • Context(org.springframework.context): ApplicationContext 接口继承自 BeanFactory,增加了特定于企业的基础功能,如AOP、事件发布、消息控制等
  • Expression:提供了一种在运行时操作对象的表达式语言
BeanFactory(基础容器)
notion image
BeanFactory 接口定义了管理 bean 的最基本方法,如 getBean()、getType()等 BeanFactory 有多个子接口,扩展了与 bean 相关的功能,其中:
  • HierarchicalBeanFactory:扩展实现了 bean 工厂的分层
  • ListableBeanFactory:扩展实现了根据条件返回 bean 集合的功能
ApplicationContext(高级容器)
notion image
ApplicationContext 是 BeanFactory 的子接口,在其基础上提供了其他高级特性
开发者提供配置元数据(configuration metadata)由 spring 容器读取这些组件后进行实例化、配置和组装为 spring bean到容器内,以BeanDefinition对象表示。
spring bean 用 bean name 作为唯一标识,约定用小驼峰格式命名。
配置元数据的方式:
  • 基于XML配置
  • 基于注解配置
    • 通常指在类上使用@Component@Service@Repository@Controller等注解的组件,在业务逻辑类上标注
  • 基于java配置
    • 通常指在@Configuration类中使用@Bean注解手动定义和配置Bean,适合集中管理Bean的配置,尤其是涉及到多个Bean的依赖、条件化配置或第三方库的集成时
依赖注入的方式:
  • 基于构造器注入(首选)
    • 通常会将依赖项字段声明为 final 字段,在类中是必须的,依赖项在运行时不可变,不能为null,否则实例化时报异常
  • 基于setter方法注入
    • 依赖项在类中是可选的,允许赋默认值,在运行时可以动态配置,可以为null,更灵活
依赖注入的模式:
  • @Autowired
    • 按类型注入,如果根据类型找到了多个,则需要用 @Qualifier 来具体指定,否则抛出异常
  • @Resource
    • 按名称注入,如果未匹配到名称,则退回到按类型注入
bean 的作用域:
bean 的生命周期回调:
  • 初始化回调
    • 在Bean被完全构建和注入完依赖后,立即执行一些初始化操作,如预加载数据、设置一些初始状态的场景,可手动实现 InitializingBean 接口,但推荐直接用@PostConstrust
  • 销毁回调
    • 在Bean被销毁前执行一些清理操作,如资源释放、关闭连接、终止线程或保存状态的场景,可手动实现 DisposableBean 接口,但推荐直接用@PreDestroy

AOP

  • 切面:标注@Aspect的类,实现"增强"功能,与业务逻辑分离,独立存在
  • 连接点:通常是方法的调用点
  • 通知:在特定连接点周围执行的增强代码
  • 切点:用切点表达式指定在哪些连接点上执行通知
    • 示例
      切点表达式指示符
      匹配规则
      示例
      方法执行
      execution(* com.example.service.*.*(..))
      指定类型中的连接点
      within(com.example.service.*)
      具有指定注解的方法
      @annotation(org.springframework.transaction.annotation.Transactional)
      目标对象类型的连接点
      target(com.example.service.MyService)
      代理对象类型的连接点
      this(com.example.service.MyService)
  • 引入:为目标对象动态添加新的方法或属性
  • 目标对象:被增强的对象
  • AOP代理:通过JDK或CGLIB生成的目标对象代理
  • 织入:将增强功能和目标对象连接
通知类型:

动态代理

 
代理模式:提供一个代理对象来控制被代理对象的访问,在客户端和原对象之前起到中介的作用
当一个对象不适合或不能直接引用另一对象时,使用代理模式可以起到隔离作用,代理类和被代理类实现相同的接口,还可以通过代理类增加额外功能来扩展被代理类,符合代码设计的开闭原则
代理模式的角色
  • 抽象主题(Subject):代理类和被代理类的共同接口
  • 具体主题(RealSubject):被代理类
  • 代理主题(Proxy):代理类
静态代理
抽象主题:创建一个接口
具体主题:创建被代理类
代理主题:创建代理类
测试
执行结果
  • 优点:在不改变原类代码的前提下,对其进行功能扩展
  • 缺点:越多的扩展,导致实现相同接口的代理类增多,难以维护
JDK 动态代理
核心代码:Proxy.newProxyInstance(类加载器,接口,InvocationHandler)
测试
CGLIB 动态代理
对于没有接口的类,使用 CGLIB 实现动态代理 核心代码:Enhancer.create(反射类型,MethodInterceptor)
 
 

Springboot 官方文档笔记

4.4 第一个应用程序

第一个pom.xml文件
第一个MyApplication.java文件
@SpringBootApplication元注解组成
  • @SpringBootConfiguration:开启额外bean注册或配置类导入功能
  • @EnableAutoConfiguration:开启springboot自动配置机制
  • @ComponentScan:开启扫描包中的@Component组件
run方法含义
  • 通过反射的Class对象告诉spring哪个类是应用程序主组件
  • 通过args传递命令行参数

6.1 构建系统

依赖管理
Springboot 每次发布都内置了其生态系统下其他依赖的版本,通过引入spring-boot-starter-parent管理版本
引入其他依赖就不再需要指定版本
假如某个依赖想自定义版本,可以引入spring-boot-dependencies管理,而不使用spring-boot-starter-parent,它可以获得同样的好处,但更灵活
如何选择?
  • spring-boot-starter-parent 继承 Spring Boot 父 POM,提供默认配置和插件管理,适用于简单配置和快速启动项目
  • spring-boot-dependencies 作为 BOM 导入依赖版本管理,允许自定义父 POM 和构建配置,适用于需要灵活性和自定义配置的复杂项目
Maven
引入springboot提供的插件才能使maven编译打包springboot应用

7.1 应用启动

自定义 banner
在classpath下或spring.banner.location属性指定的位置添加 banner.txt 文件
内置变量有:
  • ${application.version}
  • ${application.formatted-version}
  • ${spring-boot.version}
  • ${spring-boot.formatted-version}
  • ${Ansi.NAME} (or ${AnsiColor.NAME}, ${AnsiBackground.NAME}, ${AnsiStyle.NAME})
  • ${application.title}
自定义事件和监听
有时候某些事件是在ApplicationContext创建前触发的,此时监听器还没注册成@Bean,这时可以通过SpringApplication.addListeners(…)方法注册监听器
如果想注册一个不管应用如何创建都能在启动前自动注册的监听器,可以添加一个META-INF/spring.factories文件,并如下配置
获取启动参数
org.springframework.boot.ApplicationArguments这个bean提供了获取原始启动参数的能力
在启动后立即执行代码
如果在SpringApplication.run(…)执行时,且ApplicationContext准备完成后立即执行某些代码
可以实现ApplicationRunnerCommandLineRunner接口的run方法

7.2 外部配置

在命令行添加配置属性
属性占位符
属性绑定
@Value
@ConfigurationProperties
通过读取配置文件直接绑定一系列属性到标准的javabean类,通常是一个公共属性类
springboot依赖这个类的无参构造器实现自动绑定
对应配置文件的属性
  • my.service.enabled:默认值为 false
  • my.service.remote-address:可以转换为相应类型的字符串
  • my.service.security.username:有一个 SecurityProperties 嵌套对象,其名称由对象属性名确定
  • my.service.security.password:密码同理
  • my.service.security.roles:一个字符串集合,默认值为 USER
在需要明确指定的情况下,特别是在开发自定义配置或有条件地启用配置时 ,用@EnableConfigurationProperties 注解显示启用@ConfigurationProperties 类的加载和绑定,且写在 @Configuration 类上,更符合 Spring Boot 的最佳实践,提高可读性
绑定成功后就可以在其他类中直接注入使用,如

7.3 配置文件

加载顺序
  1. classpath 目录(默认src/main/resources/)
  1. classpath 目录下的 config 目录(src/main/resources/config/)
  1. 当前目录(默认项目跟路径)
  1. 当前目录下的 config 目录
按加载顺序后面的属性覆盖前面的,带profile的覆盖不带profile的
application.ymlapplication-{profile}.yml
多环境区分配置,创建application-dev.ymlapplication-prod.ymlapplication-test.yml
通过在application.yml中设置spring.profiles.active来指定环境,如在开发环境时
如果想针对组件拆分更细的配置文件,如生产下又拆分出 application-proddb.ymlapplication-prodmq.yml
通过在application.yml中设置spring.profiles.group来指定

7.4 日志

springboot 内置 LogbackSLF4JLog4j2Java Util Logging日志框架,默认实现Logback
通过logback-spring.xml(推荐)或logback.xml(不推荐)文件配置
一个配置模板:

7.12 自定义自动配置

springboot通过检查spring-boot-autoconfigure包和自己的jar包中的固定格式文件来获取所有自动配置
版本
文件
SB2
META-INF/spring.factories
SB3
META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
这也说明了,自动配置类并不是通过@ComponentScan自动扫描注册成组件的,而是从上面的文件中导入注册的
因此,自动配置类中如果还要导入其他外部配置类,应该用@Import注解导入,同样也会将它们注册为组件
如果要自定义自动配置(官方简称其为acme),通常需要两个包:
  • 自动配置模块包:包含关于"acme"配置类的模块
  • 启动器包:只提供关于"acme"自动配置模块的所有依赖
如果自动配置相对简单且没有可选特性,也可以将两个模块合并在一起直接作为starter
编写自己的starter,请遵循以下规则:
  • 模块命名应该按照acme-spring-boot-starter格式
  • 如果提供了配置健(即@ConfigurationProperties类),请给一个合适的命名空间(即prefix)
  • 使用注解处理器生成元数据文件(META-INF/spring-autoconfigure-metadata.properties
添加依赖即可生成该文件,它会用于提前过滤不匹配的自动配置,从而提高启动时间
同时需要在打包时排除这个依赖
上一篇
JavaScript 核心
下一篇
SpringSecurity6