spring(一)

导航

核心模块

  • spring core:核心类库,提供 ioc
  • spring context:提供框架式的 Bean 访问方式,以及企业级功能(JNDI(Java Naming and Directory Interface,Java 命名和目录接口)、定时任务等)
  • spring aop:aop
  • spring dao:对 jdbc 进行了抽象,简化了数据访问异常等处理
  • spring orm:对现有的 orm 框架提供了支持
  • spring web:提供了基本的面向 web 的综合特性
  • spring mvc:提供 mvc 实现

ioc

也叫控制反转,将对象间的依赖关系交给 spring 容器控制,由主动创建对象变成了被动方式,实现了解耦。可以通过@Autowired 和@Resource 来注入对象。被注入的对象必须被下面的注解标注:

  • @Controller
  • @Service
  • @Repository
  • @Component

aop

  • Joinpoint(连接点):类里面可以被增强的方法,这些方法称为连接点
  • Pointcut(切入点):所谓切入点是指我们要对哪些 Joinpoint 进行拦截的定义
  • Advice(通知/增强):所谓通知是指拦截到 Joinpoint 之后所要做的事情就是通知。
  • Aspect(切面):是切入点和通知(引介)的结合
  • Introduction(引介):引介是一种特殊的通知在不修改类代码的前提下,Introduction 可以在运行期为类动态地添加一些方法或属性
  • Target(目标对象):代(dai)理的目标对象(要增强的类)
  • Weaving(织入):是把增强应用到目标的过程,把 advice 应用到 target 的过程
  • Proxy(代(dai)理):一个类被 AOP 织入增强后,就产生一个结果代(dai)理类

切入点就是在类里边可以有很多方法被增强,比如实际操作中,只是增强了个别方法,则定义实际被增强的某个方法为切入点;通知/增强就是指增强的逻辑,比如扩展日志功能,这个日志功能称为增强;切面就是把增强应用到具体方法上面的过程称为切面。

两种实现方式

  • jdk 动态代理
    • 对实现了接口的类生成代理,该目标类型实现的接口都将被代理
    • 原理是通过在运行期间创建一个接口的实现类来完成对目标对象的代理
  • cglib
    • 针对类实现代理,对是否实现接口无要求
    • 原理是对指定的类生成一个子类,覆盖其中的方法,因为是继承,所以被代理的类或方法不可以声明为 final 类型
  • 如果该类实现了接口,默认采用 jdk 动态代理,也可强制使用 cglib

主要类

  • beanfactory
    • ioc 容器最顶层的接口
    • 作用:管理 bean,即实例化、定位、配置应用程序中的对象及建立这些对象之间的依赖
  • factoryBean
    • 生产其他的 bean 实例
  • applicationContext
    • beanfactory 的派生接口
      • 区别
        • BeanFactory:采用的是延迟加载形式来注入 Bean 的
        • ApplicationContext,它是在容器启动时,一次性创建了所有的 Bean
    • 提供了额外功能
      • 继承了 MessageSource,支持国际化。
      • 提供了统一的资源文件访问方式。
      • 提供在 Listener 中注册 Bean 的事件。
      • 提供同时加载多个配置文件的功能。
      • 载入多个(有继承关系)上下文,使得每一个上下文都专注于一个特定的层次,比如应用的 web 层。
    • 常见实现类
      • FileSystemXmlApplicationContext
      • ClassPathXmlApplicationContext
      • WebXmlApplicationContext

bean

生命周期

创建过程

循环依赖

  • 构造器循环依赖:无法解决
  • 单例 setter 注入
    • 有 aop 增强:无法解决,若 allowRawInjectionDespiteWrapping=false 报错,否则注入的是原始对象而不是代理后的对象
    • 无 aop 增强:利用三级缓存解决
  • 非单例:无法解决

三级缓存

  • 一级缓存 singletonObjects
    • 存放已经初始化好的 bean 实例
  • 二级缓存 earlySingletonObjects
    • bean 未被 aop 代理:保存半成品 bean(属性未填充,未执行初始化方法)
    • bean 被 aop 代理:保存代理的 bean 实例 beanProxy,目标 bean 仍然是半成品
  • 三级缓存 singleFactories
    • 存放 ObjectFactory,objectFactory.getObject()实际调用 getEarlyBeanReference 方法,有代理则返回代理后的 bean,否则返回原始 bean
1
2
3
4
5
6
7
8
9
10
11
12
protected Object getEarlyBeanReference(String beanName, RootBeanDefinition mbd, Object bean) {
Object exposedObject = bean;
if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
for (BeanPostProcessor bp : getBeanPostProcessors()) {
if (bp instanceof SmartInstantiationAwareBeanPostProcessor) {
SmartInstantiationAwareBeanPostProcessor ibp = (SmartInstantiationAwareBeanPostProcessor) bp;
exposedObject = ibp.getEarlyBeanReference(exposedObject, beanName);
}
}
}
return exposedObject;
}
  1. 一、二、三级缓存中寻找 A,未找到,实例化 A
  2. 实例化 A,此时 A 是个半成品,加入三级缓存 singleFactories
  3. 为 A 注入对象,发现需要 B 对象
  4. 一、二、三级缓存中寻找 B,未找到,实例化 B
  5. 实例化 B,此时 B 是个半成品,加入三级缓存 singleFactories
  6. 为 B 注入对象,发现需要 A 对象,发现 A 对象在三级缓存中
  7. 添加 A 至二级缓存 earlySingletonObjects,移除三级缓存中 A
  8. 将 A 注入 B
  9. B 完成属性填充,执行初始化方法
  10. B 是否在二级缓存。若在,说明被循环依赖,根据是否有 aop 代理和 allowRawInjectionDespiteWrapping 配置决定是否报错
  11. B 加入一级缓存 singletonObjects,移除二、三级缓存中 B
  12. A 注入对象 B
  13. A 完成属性填充,执行初始化方法
  14. A 是否在二级缓存。若在,说明被循环依赖,根据是否有 aop 代理和 allowRawInjectionDespiteWrapping 配置决定是否报错
  15. A 加入一级缓存 singletonObjects,移除二、三级缓存中 A

作用域

  • singleton:默认
  • prototype:原型模式,每次都 new
  • request:每 http 请求产生新实例,只在 web 应用有效
  • session:每 http session 产生新实例,只在 web 应用有效
  • global session:每全局的 session 产生新实例,只在 web 应用有效

事务

  • 编程式事务管理:使用 TransactionTemplate 实现
  • 声明式事务管理:建立在 aop 之上——目标方法开始前加入一个事务,执行完目标方法后提交或回滚事务

  • 传播级别

    • PROPAGATION_REQUIRED:如果当前没有事务,就创建一个新事务,如果当前存在事务,就加入该事务,该设置是最常用的设置。
    • PROPAGATION_SUPPORTS:支持当前事务,如果当前存在事务,就加入该事务,如果当前不存在事务,就以非事务执行。
    • PROPAGATION_MANDATORY:支持当前事务,如果当前存在事务,就加入该事务,如果当前不存在事务,就抛出异常。
    • PROPAGATION_REQUIRES_NEW:创建新事务,无论当前存不存在事务,都创建新事务。
    • PROPAGATION_NOT_SUPPORTED:以非事务方式执行操作,如果当前存在事务,就把当前事务挂起。
    • PROPAGATION_NEVER:以非事务方式执行,如果当前存在事务,则抛出异常。
    • PROPAGATION_NESTED:如果当前存在事务,则在嵌套事务内执行。如果当前没有事务,则按 REQUIRED 属性执行。
  • 隔离级别
    • 读未提交
    • 读已提交
    • 可重复读
    • 串行

springmvc

消息处理流程

springboot

  • @SpringBootApplication
    • @SpringBootConfiguration:组合了@Configuration 注解,实现配置文件的功能
    • @EnableAutoConfiguration:通过 META-INF/spring.factories 的配置,并结合 @Condition 条件,完成 bean 的注册;
    • @ComponentScan

启动流程

new SpringAppliction().run()

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
// new SpringAppliction()
public SpringApplication(ResourceLoader resourceLoader, Class<?>... primarySources) {
this.resourceLoader = resourceLoader;
Assert.notNull(primarySources, "PrimarySources must not be null");
this.primarySources = new LinkedHashSet<>(Arrays.asList(primarySources));
// 确定应用类型,servlet、reactive、none
this.webApplicationType = WebApplicationType.deduceFromClasspath();

// 加载bootstrap初始化器,从META-INF/spring.factories文件读取
this.bootstrapRegistryInitializers = new ArrayList<>(
getSpringFactoriesInstances(BootstrapRegistryInitializer.class));
// 加载初始化器,从META-INF/spring.factories文件读取
setInitializers((Collection) getSpringFactoriesInstances(ApplicationContextInitializer.class));
// 加载监听器,从META-INF/spring.factories文件读取
setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));
// 设置主类
this.mainApplicationClass = deduceMainApplicationClass();
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
// run()
public ConfigurableApplicationContext run(String... args) {
// 记录开始时间
long startTime = System.nanoTime();
// 创建bootstrap上下文
DefaultBootstrapContext bootstrapContext = createBootstrapContext();

ConfigurableApplicationContext context = null;
// 设置headless
configureHeadlessProperty();
// 获取SpringApplicationRunListener接口下监听器
// 默认实现类EventPublishingRunListener,会利用一个广播监听器向所有ApplicationListener广播各种SpringApplicationEvents
SpringApplicationRunListeners listeners = getRunListeners(args);
// SpringApplicationRunListener下starting事件
listeners.starting(bootstrapContext, this.mainApplicationClass);
try {
// 设置应用参数(main参数args)
ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
// 加载环境变量(各种配置属性)
ConfigurableEnvironment environment = prepareEnvironment(listeners, bootstrapContext, applicationArguments);
// 打印banner
Banner printedBanner = printBanner(environment);
// 创建上下文(根据webApplicationType应用类型)
context = createApplicationContext();
context.setApplicationStartup(this.applicationStartup);
// 准备上下文,设置context的配置变量、bean生成器、资源加载器,初始化器执行初始化方法等
// 创建BeanDefinitionLoader,加载启动类,将启动类注入容器
prepareContext(bootstrapContext, context, environment, listeners, applicationArguments, printedBanner);
// 刷新上下文,加载bean
refreshContext(context);
// 刷新后续处理,扩展方法,没有提供任何默认的实现,我们自定义的子类可以进行扩展
afterRefresh(context, applicationArguments);
Duration timeTakenToStartup = Duration.ofNanos(System.nanoTime() - startTime);
if (this.logStartupInfo) {
new StartupInfoLogger(this.mainApplicationClass).logStarted(getApplicationLog(), timeTakenToStartup);
}
listeners.started(context, timeTakenToStartup);
// 执行容器中的ApplicationRunner和CommandLineRunner类型的bean的run方法
callRunners(context, applicationArguments);
}
catch (Throwable ex) {
if (ex instanceof AbandonedRunException) {
throw ex;
}
handleRunFailure(context, ex, listeners);
throw new IllegalStateException(ex);
}
try {
if (context.isRunning()) {
// 启动耗时
Duration timeTakenToReady = Duration.ofNanos(System.nanoTime() - startTime);
listeners.ready(context, timeTakenToReady);
}
}
catch (Throwable ex) {
if (ex instanceof AbandonedRunException) {
throw ex;
}
handleRunFailure(context, ex, null);
throw new IllegalStateException(ex);
}
return context;
}