type
status
date
slug
summary
tags
category
icon
password
Spring 基础
IOC(Inversion of Control)
- Core:使用了 IoC 设计思想提供了 DI 功能
- Beans(
org.springframework.beans
):BeanFactory 接口,提供配置机制,可以管理任何类型的对象
- Context(
org.springframework.context
): ApplicationContext 接口继承自 BeanFactory,增加了特定于企业的基础功能,如AOP、事件发布、消息控制等
- Expression:提供了一种在运行时操作对象的表达式语言
BeanFactory(基础容器)
BeanFactory 接口定义了管理 bean 的最基本方法,如 getBean()、getType()等
BeanFactory 有多个子接口,扩展了与 bean 相关的功能,其中:
- HierarchicalBeanFactory:扩展实现了 bean 工厂的分层
- ListableBeanFactory:扩展实现了根据条件返回 bean 集合的功能
ApplicationContext(高级容器)
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
准备完成后立即执行某些代码可以实现
ApplicationRunner
或CommandLineRunner
接口的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 配置文件
加载顺序
- classpath 目录(默认src/main/resources/)
- classpath 目录下的 config 目录(src/main/resources/config/)
- 当前目录(默认项目跟路径)
- 当前目录下的 config 目录
按加载顺序后面的属性覆盖前面的,带profile的覆盖不带profile的
application.yml
和 application-{profile}.yml
多环境区分配置,创建
application-dev.yml
、application-prod.yml
、application-test.yml
通过在
application.yml
中设置spring.profiles.active
来指定环境,如在开发环境时如果想针对组件拆分更细的配置文件,如生产下又拆分出
application-proddb.yml
和 application-prodmq.yml
通过在
application.yml
中设置spring.profiles.group
来指定7.4 日志
springboot 内置
Logback
、SLF4J
、Log4j2
、Java 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
)
添加依赖即可生成该文件,它会用于提前过滤不匹配的自动配置,从而提高启动时间
同时需要在打包时排除这个依赖
- Author:风之旅人
- URL:https://www.hrmi.fun//article/springboot
- Copyright:All articles in this blog, except for special statements, adopt BY-NC-SA agreement. Please indicate the source!