Spring 基础

Spring 基础

Spring 最重要的特性就是控制反转、依赖注入和面向切面编程

这三个特性都不是 Spring 提出的,只是使用

而 DI 是 IOC 的一种实现方式

基本概念

IOC

IOC: Inversion of Control

在 Spring 里,控制反转就是使用者把对象的控制权交给 Spring

反转的是自己对对象的控制,这个控制交给 Spring

Spring 控制的是 bean 的创建、管理和生命周期

DI

DI: Dependency Injection

DI 是 IOC 的实现方式

对象的创建需要外部的各种资源,如数据、文件、对象等

Spring 把这些资源自动帮你注入到 bean,顺带着帮你维护 bean 之间的依赖关系

组成

  • 总共 8 个模块,每个模块既可以单独使用,又可与其他模块联合使用
Spring

绿色表示一个模块

黑色表示 jar 包

( SpEL, Spring Express Language )

Bean

  • bean 是 Spring 帮你自己的对象穿上衣服,形成的对象

在 Spring 中,操作的都是 bean,bean 在 Spring 实现中是 BeanDefinition

容器

容器管理着 bean 的生命周期,控制着 bean 的依赖注入

image-20201218232252496

有两个接口定义 容器的根本

  • BeanFactory

    • BeanFactory 代表 低级容器,基本就是个 MapkeyBeanNamevalueBean 实例。通常只提供注册(put),获取(get)这两个功能
  • ApplicationContext

    • ApplicationContext 代表 高级容器,提供了更全面、高级的功能,例如获取资源,发布事件等

      ApplicationContext 就是升级版的 BeanFactory

    • ApplicationContext 继承自 BeanFactory,但是它不应该被理解为 BeanFactory 的实现类,而是说其内部持有一个实例化的 BeanFactory(DefaultListableBeanFactory)。以后所有的 BeanFactory 相关的操作其实是委托给这个实例来处理的

image-20201218233344457

  • ListableBeanFactory: 通过这个接口,可以获取多个 Bean

    • 最顶层 BeanFactory 接口的方法 都是获取单个 Bean 的
  • HierarchicalBeanFactory: 可以在应用中起 多个 BeanFactory,然后可以将各个 BeanFactory 设置为父子关系

  • AutowireCapableBeanFactory: 用来自动装配 Bean 用的,但是 ApplicationContext 并没有继承它

    • ApplicationContext 接口定义的 getAutowireCapableBeanFactory 可拿到
  • ConfigurableListableBeanFactory: 它继承了上面的三个接口

应用上下文

ApplicationContext 作为基本的应用上下文接口,有不同的实现类

常用的就是

  • AnnotationConfigApplicationContext: 基于注解,不需要配置文件
  • ClassPathXmlApplicationContext: classpath 下的 xml 配置文件
  • FileSystemXmlApplicationContext: 系统下的 xml 配置文件

容器启动过程

ClassPathXmlApplicationContext 为例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
public class Car {
private String brand;
private int age;

public Car(){
System.out.println("constructor");
}

public void setAge(int age){
this.age = age;
}
public void setBrand(String brand){
this.brand = brand;
}

public String toString(){
return "brand:" + this.brand + ",age:" + this.age;
}

}
1
2
3
4
5
6
7
8
9
10
<?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/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

<bean id="car" class="cn.kebabshell.learn.bean.Car">
<property name="age" value="12" />
<property name="brand" value="bmw" />
</bean>
</beans>
1
2
3
4
5
6
7
8
public static void main(String[] args) {
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("services.xml");

Car car = applicationContext.getBean("car", Car.class);

System.out.println(car);

}

在构造中

1
2
3
4
5
6
7
8
9
10
11
public ClassPathXmlApplicationContext(
String[] configLocations, boolean refresh, @Nullable ApplicationContext parent)
throws BeansException {

super(parent);
setConfigLocations(configLocations);
if (refresh) {
// 重中之重,初始化和运行时刷新
refresh();
}
}

refresh

关于 BeanPostProcessorBeanFactoryPostProcessor看这里

实例化的意思在对象还未生成,初始化的意思在对象已经生成

重点:finishBeanFactoryInitialization

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
64
65
66
67
68
69
70
71
72
73
74
75
76
77
public void refresh() throws BeansException, IllegalStateException {
// 互斥锁,不然 refresh 还没结束,又来个启动或销毁容器的操作,就乱了
synchronized (this.startupShutdownMonitor) {

// 准备工作,记录下容器的启动时间、标记“已启动”状态、处理配置文件中的占位符
prepareRefresh();

// 这步比较关键,这步完成后,配置文件就会解析成一个个 Bean 定义,注册到 BeanFactory 中
// 当然,这里说的 Bean 还没有实例化,只是配置信息都提取出来了
// 注册也只是将这些信息都保存到了注册中心
// ( 说到底核心是一个 beanName-> beanDefinition 的 map )
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

// 设置 BeanFactory 的类加载器,添加几个 BeanPostProcessor,手动注册几个特殊的 bean
prepareBeanFactory(beanFactory);

try {
// Bean 如果实现了接口 BeanFactoryPostProcessor
// 在容器实例化之前,会调用 postProcessBeanFactory 方法

// 这里是提供给子类的扩展点,到这里的时候,所有的 Bean 都找到了、注册完成了,但是都还没有实例化
// 具体的子类可以在这步的时候添加一些特殊的 BeanFactoryPostProcessor 的实现类或做点什么事
// 如修改 BeanDefinition
postProcessBeanFactory(beanFactory);

// 调用 BeanFactoryPostProcessor 各个实现类的 postProcessBeanFactory(factory) 回调方法
invokeBeanFactoryPostProcessors(beanFactory);

// 注册 BeanPostProcessor 的实现类,注意看和 BeanFactoryPostProcessor 的区别
// 此接口有两个方法: postProcessBeforeInitialization 和 postProcessAfterInitialization
// 两个方法分别在 Bean 初始化之前和初始化之后得到执行
// 这里仅仅是注册,之后会在 doCreateBean 看到回调这两方法的时机
registerBeanPostProcessors(beanFactory);

// 初始化当前 ApplicationContext 的 MessageSource,国际化
initMessageSource();

// 初始化当前 ApplicationContext 的事件广播器
initApplicationEventMulticaster();

// 模板方法
// 子类可以在这里初始化一些特殊的 Bean( 在初始化 singleton beans 之前 )
onRefresh();

// 注册事件监听器,监听器需要实现 ApplicationListener 接口
registerListeners();

// 重点,重点,重点
// 初始化所有的 singleton beans
// ( lazy-init 的除外 )
finishBeanFactoryInitialization(beanFactory);

// 最后,广播事件,ApplicationContext 初始化完成
finishRefresh();
}

catch (BeansException ex) {
// log

// Destroy already created singletons to avoid dangling resources.
// 销毁已经初始化的 singleton 的 Beans,以免有些 bean 会一直占用资源
destroyBeans();

// Reset 'active' flag.
cancelRefresh(ex);

// 把异常往外抛
throw ex;
}

finally {
// Reset common introspection caches in Spring's core, since we
// might not ever need metadata for singleton beans anymore...
resetCommonCaches();
}
}
}
1、prepareRefresh

创建 Bean 容器前的准备工作

  • 记录启动时间
  • 校验 xml 配置文件
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
protected void prepareRefresh() {
// Switch to active.
this.startupDate = System.currentTimeMillis();
this.closed.set(false);
this.active.set(true);

// logger...

// Initialize any placeholder property sources in the context environment.
initPropertySources();

// Validate that all properties marked as required are resolvable:
// see ConfigurablePropertyResolver#setRequiredProperties
getEnvironment().validateRequiredProperties();

// Store pre-refresh ApplicationListeners...
if (this.earlyApplicationListeners == null) {
this.earlyApplicationListeners = new LinkedHashSet<>(this.applicationListeners);
}
else {
// Reset local application listeners to pre-refresh state.
this.applicationListeners.clear();
this.applicationListeners.addAll(this.earlyApplicationListeners);
}

// Allow for the collection of early ApplicationEvents,
// to be published once the multicaster is available...
this.earlyApplicationEvents = new LinkedHashSet<>();
}
2、obtainFreshBeanFactory

初始化 BeanFactory、加载 Bean、注册 Bean 等等

这步结束后,Bean 并没有完成实例化和初始化

注册也只是将这些信息都保存到了一个 map 里

1
2
3
4
protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
refreshBeanFactory();
return getBeanFactory();
}

refreshBeanFactory

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
protected final void refreshBeanFactory() throws BeansException {
if (hasBeanFactory()) {
destroyBeans();
closeBeanFactory();
}
try {
DefaultListableBeanFactory beanFactory = createBeanFactory();
beanFactory.setSerializationId(getId());
// 配置是否允许 BeanDefinition 覆盖、是否允许循环引用
customizeBeanFactory(beanFactory);
loadBeanDefinitions(beanFactory);
synchronized (this.beanFactoryMonitor) {
this.beanFactory = beanFactory;
}
}
catch (IOException ex) {
// throw...
}
}

customizeBeanFactory

1
2
3
4
5
6
7
8
protected void customizeBeanFactory(DefaultListableBeanFactory beanFactory) {
if (this.allowBeanDefinitionOverriding != null) {
beanFactory.setAllowBeanDefinitionOverriding(this.allowBeanDefinitionOverriding);
}
if (this.allowCircularReferences != null) {
beanFactory.setAllowCircularReferences(this.allowCircularReferences);
}
}

配置是否允许 BeanDefinition 覆盖、是否允许循环引用

BeanDefinition 的覆盖问题可能会有开发者碰到这个坑,就是在配置文件中定义 bean 时使用了相同的 id 或 name,默认情况下,allowBeanDefinitionOverriding 属性为 null,如果在同一配置文件中重复了,会抛错,但是如果不是同一配置文件中,会发生覆盖

循环引用即:A 依赖 B,而 B 依赖 A。或 A 依赖 B,B 依赖 C,而 C 依赖 A

默认情况下,Spring 允许循环依赖,当然如果你在 A 的构造方法中依赖 B,在 B 的构造方法中依赖 A 是不行的

loadBeanDefinitions

根据配置,加载各个 Bean,然后放到 BeanFactory

读取配置的操作在 XmlBeanDefinitionReader 中,其负责加载配置、解析

1
2
3
4
// XmlBeanDefinitionReader
public int loadBeanDefinitions(Resource resource) throws BeanDefinitionStoreException {
return loadBeanDefinitions(new EncodedResource(resource));
}
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
public int loadBeanDefinitions(EncodedResource encodedResource) throws BeanDefinitionStoreException {
Assert.notNull(encodedResource, "EncodedResource must not be null");
// logger...

Set<EncodedResource> currentResources = this.resourcesCurrentlyBeingLoaded.get();

if (!currentResources.add(encodedResource)) {
// throw...
}

try (InputStream inputStream = encodedResource.getResource().getInputStream()) {
InputSource inputSource = new InputSource(inputStream);
if (encodedResource.getEncoding() != null) {
inputSource.setEncoding(encodedResource.getEncoding());
}
return doLoadBeanDefinitions(inputSource, encodedResource.getResource());
}
catch (IOException ex) {
// throw...
}
finally {
currentResources.remove(encodedResource);
if (currentResources.isEmpty()) {
this.resourcesCurrentlyBeingLoaded.remove();
}
}
}

doRegisterBeanDefinitions

  • 解析标签
  • 注册
  • 此时 Bean 依然还没有实例化初始化
1
2
3
4
5
6
7
8
9
10
11
12
13
protected int doLoadBeanDefinitions(InputSource inputSource, Resource resource)
throws BeanDefinitionStoreException {

try {
// 解析
Document doc = doLoadDocument(inputSource, resource);
// 注册
int count = registerBeanDefinitions(doc, resource);
// logger...
return count;
}
// catch throw...
}
3、prepareBeanFactory

设置 BeanFactory 的类加载器,添加几个 BeanPostProcessor,Spring 手动注册几个 bean

如果没有定义 environment systemProperties systemEnvironment 这几个 bean,那么 Spring 会 “手动” 注册一个

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
protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) {
// Tell the internal bean factory to use the context's class loader etc.
beanFactory.setBeanClassLoader(getClassLoader());
beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader()));
beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment()));

// Configure the bean factory with context callbacks.
beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));
beanFactory.ignoreDependencyInterface(EnvironmentAware.class);
beanFactory.ignoreDependencyInterface(EmbeddedValueResolverAware.class);
beanFactory.ignoreDependencyInterface(ResourceLoaderAware.class);
beanFactory.ignoreDependencyInterface(ApplicationEventPublisherAware.class);
beanFactory.ignoreDependencyInterface(MessageSourceAware.class);
beanFactory.ignoreDependencyInterface(ApplicationContextAware.class);

// BeanFactory interface not registered as resolvable type in a plain factory.
// MessageSource registered (and found for autowiring) as a bean.
beanFactory.registerResolvableDependency(BeanFactory.class, beanFactory);
beanFactory.registerResolvableDependency(ResourceLoader.class, this);
beanFactory.registerResolvableDependency(ApplicationEventPublisher.class, this);
beanFactory.registerResolvableDependency(ApplicationContext.class, this);

// Register early post-processor for detecting inner beans as ApplicationListeners.
beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(this));

// Detect a LoadTimeWeaver and prepare for weaving, if found.
if (beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
// Set a temporary ClassLoader for type matching.
beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
}

// Register default environment beans.
if (!beanFactory.containsLocalBean(ENVIRONMENT_BEAN_NAME)) {
beanFactory.registerSingleton(ENVIRONMENT_BEAN_NAME, getEnvironment());
}
if (!beanFactory.containsLocalBean(SYSTEM_PROPERTIES_BEAN_NAME)) {
beanFactory.registerSingleton(SYSTEM_PROPERTIES_BEAN_NAME, getEnvironment().getSystemProperties());
}
if (!beanFactory.containsLocalBean(SYSTEM_ENVIRONMENT_BEAN_NAME)) {
beanFactory.registerSingleton(SYSTEM_ENVIRONMENT_BEAN_NAME, getEnvironment().getSystemEnvironment());
}
}
4、finishBeanFactoryInitialization

一些基本的步骤可通过 debug 查看:

image-20201229220303528

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
protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {
// Initialize conversion service for this context.
// 初始化名字为 conversionService 的 Bean
if (beanFactory.containsBean(CONVERSION_SERVICE_BEAN_NAME) &&
beanFactory.isTypeMatch(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class)) {
beanFactory.setConversionService(
beanFactory.getBean(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class));
}

// Register a default embedded value resolver if no bean post-processor
// (such as a PropertyPlaceholderConfigurer bean) registered any before:
// at this point, primarily for resolution in annotation attribute values.
if (!beanFactory.hasEmbeddedValueResolver()) {
beanFactory.addEmbeddedValueResolver(strVal -> getEnvironment().resolvePlaceholders(strVal));
}

// Initialize LoadTimeWeaverAware beans early to allow for registering their transformers early.
String[] weaverAwareNames = beanFactory.getBeanNamesForType(LoadTimeWeaverAware.class, false, false);
for (String weaverAwareName : weaverAwareNames) {
getBean(weaverAwareName);
}

// Stop using the temporary ClassLoader for type matching.
beanFactory.setTempClassLoader(null);

// Allow for caching all bean definition metadata, not expecting further changes.
// 不希望这个时候还出现 bean 定义解析、加载、注册,就得 freeze
beanFactory.freezeConfiguration();

// Instantiate all remaining (non-lazy-init) singletons.
// 对于普通的 Bean,只要调用 getBean(beanName) 这个方法就可以进行初始化了
beanFactory.preInstantiateSingletons();
}

实例化所有的 singleton beans ( 没有设置懒加载 )

preInstantiateSingletons

对于普通的 Bean,只要调用 getBean(beanName) 这个方法就可以进行实例化了

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
// DefaultListableBeanFactory
public void preInstantiateSingletons() throws BeansException {
// logger...

// Iterate over a copy to allow for init methods which in turn register new bean definitions.
// While this may not be part of the regular factory bootstrap, it does otherwise work fine.
List<String> beanNames = new ArrayList<>(this.beanDefinitionNames);

// Trigger initialization of all non-lazy singleton beans...
for (String beanName : beanNames) {
RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
if (isFactoryBean(beanName)) {
Object bean = getBean(FACTORY_BEAN_PREFIX + beanName);
if (bean instanceof FactoryBean) {
final FactoryBean<?> factory = (FactoryBean<?>) bean;
boolean isEagerInit;
if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) {
isEagerInit = AccessController.doPrivileged((PrivilegedAction<Boolean>)
((SmartFactoryBean<?>) factory)::isEagerInit,
getAccessControlContext());
}
else {
isEagerInit = (factory instanceof SmartFactoryBean &&
((SmartFactoryBean<?>) factory).isEagerInit());
}
if (isEagerInit) {
getBean(beanName);
}
}
}
else {
getBean(beanName);
}
}
}

// Trigger post-initialization callback for all applicable beans...
for (String beanName : beanNames) {
Object singletonInstance = getSingleton(beanName);
if (singletonInstance instanceof SmartInitializingSingleton) {
final SmartInitializingSingleton smartSingleton = (SmartInitializingSingleton) singletonInstance;
if (System.getSecurityManager() != null) {
AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
smartSingleton.afterSingletonsInstantiated();
return null;
}, getAccessControlContext());
}
else {
smartSingleton.afterSingletonsInstantiated();
}
}
}
}
getBean -> doGetBean -> createBean

singleton 和 prototype 分别处理

1
2
3
4
// AbstractBeanFactory
public Object getBean(String name) throws BeansException {
return doGetBean(name, null, null, false);
}
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
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
protected <T> T doGetBean(final String name, @Nullable final Class<T> requiredType,
@Nullable final Object[] args, boolean typeCheckOnly) throws BeansException {

// 如果是 FactoryBean,会去掉 Bean 开头的 & 符号
// 能存在传入别名且别名存在多重映射的情况,这里会返回最终的名字
// 如存在多层别名映射 A->B->C->D,传入 D,最终会返回 A
final String beanName = transformedBeanName(name);
Object bean;

// Eagerly check singleton cache for manually registered singletons.
// getSingleton() 方法的实现,在父类 DefaultSingletonBeanRegistry 中
Object sharedInstance = getSingleton(beanName);
// 这里先尝试从缓存中获取,若获取不到,就走下面的创建( 循环依赖 )
if (sharedInstance != null && args == null) {
// ...
}
else {
// Fail if we're already creating this bean instance:
// We're assumably within a circular reference.
// 原型对象不允许循环创建,如果是原型对象正在创建,那就抛异常
if (isPrototypeCurrentlyInCreation(beanName)) {
// throw
}

// Check if bean definition exists in this factory.
// 若存在父容器,得看看父容器是否实例化过它了,避免被重复实例化(若父容器被实例化,就以父容器的为准)
// 比如扫描 controller,哪怕不加排除什么的,也不会出问题的原因,因为 Spring 中的单例 Bean 只会被实例化一次,即使父子容器都扫描了
BeanFactory parentBeanFactory = getParentBeanFactory();
if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
// Not found -> check parent.
String nameToLookup = originalBeanName(name);
if (parentBeanFactory instanceof AbstractBeanFactory) {
return ((AbstractBeanFactory) parentBeanFactory).doGetBean(
nameToLookup, requiredType, args, typeCheckOnly);
}
else if (args != null) {
// Delegation to parent with explicit args.
return (T) parentBeanFactory.getBean(nameToLookup, args);
}
else if (requiredType != null) {
// No args -> delegate to standard getBean method.
return parentBeanFactory.getBean(nameToLookup, requiredType);
}
else {
return (T) parentBeanFactory.getBean(nameToLookup);
}
}

// alreadyCreated 字段增加此值。表示此 Bean 已经创建了
if (!typeCheckOnly) {
markBeanAsCreated(beanName);
}

try {
// 根据名字获取合并过的对应的 RootBeanDefinition
final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
checkMergedBeanDefinition(mbd, beanName, args);

// Guarantee initialization of beans that the current bean depends on.
// 我们会有属性注入等等,这里就是要保证它依赖的那些属性先初始化才行
// 这部分是处理循环依赖的核心
// @DependsOn 注解可以控制 Bean 的初始化顺序
String[] dependsOn = mbd.getDependsOn();
if (dependsOn != null) {
for (String dep : dependsOn) {
if (isDependent(beanName, dep)) {
// throw
}
registerDependentBean(dep, beanName);
try {
getBean(dep);
}
// throw
}
}

// Create bean instance.
// 开始创建 Bean 实例
// 如果是 singleton
if (mbd.isSingleton()) {
// 也是一样先尝试从缓存去获取,获取失败就通过 ObjectFactory 的 createBean 方法创建
// 这个 getSingleton 方法和上面是重载方法,它支持通过 ObjectFactory 去根据 Scope 来创建对象
sharedInstance = getSingleton(beanName, () -> {
try {
// 创建 Bean 的核心方法
return createBean(beanName, mbd, args);
}
// throw 执行失败,就销毁 Bean。然后执行对应的 destroy 方法
});
bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
}
// 如果是 prototype
else if (mbd.isPrototype()) {
// It's a prototype -> create a new instance.
Object prototypeInstance = null;
try {
beforePrototypeCreation(beanName);
prototypeInstance = createBean(beanName, mbd, args);
}
finally {
afterPrototypeCreation(beanName);
}
bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
}

// ...
}
// throw
}

// Check if required type matches the type of the actual bean instance.
if (requiredType != null && !requiredType.isInstance(bean)) {
try {
T convertedBean = getTypeConverter().convertIfNecessary(bean, requiredType);
if (convertedBean == null) {
// throw
}
return convertedBean;
}
// throw
}
return (T) bean;
}
createBean -> doCreateBean

doCreateBean 的步骤

  • 实例化,createBeanInstance
    • 工厂模式实例化,然后看参数来调用不同的构造函数
  • 解决 循环依赖
  • 前面只是实例化,这里是属性注入/设值 populateBean
  • 处理 bean 初始化完成后的各种回调 initializeBean
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
// AbstractAutowireCapableBeanFactory
protected Object createBean(String beanName,
RootBeanDefinition mbd,
@Nullable Object[] args)
throws BeanCreationException {

// logger...


RootBeanDefinition mbdToUse = mbd;

// Make sure bean class is actually resolved at this point, and
// clone the bean definition in case of a dynamically resolved Class
// which cannot be stored in the shared merged bean definition.
// 确保对应 BeanClass 完成解析(已经加载进来了 Class 对象)
// ...

// Prepare method overrides.
// ...

try {
// Give BeanPostProcessors a chance to return a proxy instead of the target bean instance.
// 给 BeanPostProcessors 一个机会来返回一个代理对象代替目标对象( AOP )
// 在所有 bean 创建之前,都会先调用 resolveBeforeInstantiation 方法
// 如果返回的 bean 为 null,就不会执行 postProcessBeforeInitialization 和 after
// 到下面才调用 doCreateBean 来创建 bean,以及执行 postProcessBeforeInitialization 和 after
// 来形成代理对象
Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
if (bean != null) {
return bean;
}
}
catch (Throwable ex) {
// throw
}

try {
Object beanInstance = doCreateBean(beanName, mbdToUse, args);
// logger..
return beanInstance;
}
// throw
}
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
protected Object doCreateBean(
final String beanName, final RootBeanDefinition mbd,
final @Nullable Object[] args)
throws BeanCreationException {

// Instantiate the bean.
// ...
if (instanceWrapper == null) {
// 实例化
instanceWrapper = createBeanInstance(beanName, mbd, args);
}
// ...

// Allow post-processors to modify the merged bean definition.
// ...

// Eagerly cache singletons to be able to resolve circular references
// even when triggered by lifecycle interfaces like BeanFactoryAware.
// ...

// Initialize the bean instance.
Object exposedObject = bean;
try {
// 属性赋值
populateBean(beanName, mbd, instanceWrapper);
// 初始化
exposedObject = initializeBean(beanName, exposedObject, mbd);
}
// throw

if (earlySingletonExposure) {
// ...
}

// Register bean as disposable.
try {
// 销毁-注册回调接口
registerDisposableBeanIfNecessary(beanName, bean, mbd);
}
// throw

return exposedObject;
}

AOP

使用

参考文章

Instantiation 表示实例化,Initialization 表示初始化

实例化的意思在对象还未生成,初始化的意思在对象已经生成

原理

之前的 文章 说到 AOP 的实现是依靠 BeanPostProcessor

AbstractAutoProxyCreator 实现了 postProcessAfterInitialization 方法

image-20201229232601261

在实例化对象之前,createBean 里面会先执行 resolveBeforeInstantiation,给 BeanPostProcessors 一个机会 来返回一个代理对象代替目标对象( AOP )

在所有 bean 创建之前,都会先调用 resolveBeforeInstantiation 方法

如果返回的 bean 为 null,就不会执行 postProcessBeforeInitializationafter 形成代理对象,到下面才调用 doCreateBean 来创建 bean

postProcessAfterInitialization

AbstractAutoProxyCreatorpostProcessAfterInitialization

1
2
3
4
5
6
7
8
9
10
public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) {
if (bean != null) {
Object cacheKey = getCacheKey(bean.getClass(), beanName);
if (this.earlyProxyReferences.remove(cacheKey) != bean) {
// 核心!!!
return wrapIfNecessary(bean, beanName, cacheKey);
}
}
return bean;
}

核心方法 wrapIfNecessary

wrapIfNecessary 会执行 createProxy 创建代理对象

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
protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
if (StringUtils.hasLength(beanName) && this.targetSourcedBeans.contains(beanName)) {
return bean;
}
if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {
return bean;
}
if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) {
this.advisedBeans.put(cacheKey, Boolean.FALSE);
return bean;
}

// Create proxy if we have advice.
Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
if (specificInterceptors != DO_NOT_PROXY) {
this.advisedBeans.put(cacheKey, Boolean.TRUE);
// createProxy 创建代理对象
Object proxy = createProxy(
bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
this.proxyTypes.put(cacheKey, proxy.getClass());
return proxy;
}

this.advisedBeans.put(cacheKey, Boolean.FALSE);
return bean;
}

createProxy 创建代理对象

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
protected Object createProxy(Class<?> beanClass, @Nullable String beanName,
@Nullable Object[] specificInterceptors, TargetSource targetSource) {

if (this.beanFactory instanceof ConfigurableListableBeanFactory) {
AutoProxyUtils.exposeTargetClass((ConfigurableListableBeanFactory) this.beanFactory, beanName, beanClass);
}

ProxyFactory proxyFactory = new ProxyFactory();
proxyFactory.copyFrom(this);

if (!proxyFactory.isProxyTargetClass()) {
if (shouldProxyTargetClass(beanClass, beanName)) {
proxyFactory.setProxyTargetClass(true);
}
else {
evaluateProxyInterfaces(beanClass, proxyFactory);
}
}

Advisor[] advisors = buildAdvisors(beanName, specificInterceptors);
proxyFactory.addAdvisors(advisors);
proxyFactory.setTargetSource(targetSource);
customizeProxyFactory(proxyFactory);

proxyFactory.setFrozen(this.freezeProxy);
if (advisorsPreFiltered()) {
proxyFactory.setPreFiltered(true);
}

return proxyFactory.getProxy(getProxyClassLoader());
}

ProxyFactorygetProxy

1
2
3
public Object getProxy(@Nullable ClassLoader classLoader) {
return createAopProxy().getProxy(classLoader);
}

DefaultAopProxyFactory 继承了 AopProxyFactory

1
2
3
public interface AopProxyFactory {
AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException;
}

来到子类 DefaultAopProxyFactorycreateAopProxy,这里会看是 JDKProxy 还是 CglibProxy

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
if (config.isOptimize() || config.isProxyTargetClass() || hasNoUserSuppliedProxyInterfaces(config)) {
Class<?> targetClass = config.getTargetClass();
if (targetClass == null) {
// throw...
}
if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) {
// JDKProxy
return new JdkDynamicAopProxy(config);
}
// CglibProxy
return new ObjenesisCglibAopProxy(config);
}
else {
return new JdkDynamicAopProxy(config);
}
}
JDK or Cglib

image-20201229235830676

JDKProxy 以及 CglibProxy 这两种生成代理对象的方式在 AOP 中分别对应两个类:JdkDynamicAopProxyCglibAopProxy,而 AopProxy 是这两个类的父接口

代理生成后会保存到 BeanWrappper 包装类里面,通过容器的 getBean() 方法获得的对象就是通过 JDK 或者 Cglib 生成的代理对象,我们使用的都是 代理对象

  • JDKProxy 实现是通过把 Advised 封装到 InvocationHandler 中实现的
  • CglibProxy 实现是通过把 Advised 封装到 MethodInterceptor 中实现的
对 JDKProxy 来说

getProxy 方法里面,会:

  • 获取代理类要实现的接口,除了 Advised 对象中配置的,还会加上 SpringProxyAdvised(opaque = false)

  • 检查上面得到的接口中有没有定义 equals 或者 hashcode 的接口

  • 调用 Proxy.newProxyInstance 创建代理对象

1
2
3
4
5
6
public Object getProxy(@Nullable ClassLoader classLoader) {
// logger...
Class<?>[] proxiedInterfaces = AopProxyUtils.completeProxiedInterfaces(this.advised, true);
findDefinedEqualsAndHashCodeMethods(proxiedInterfaces);
return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this);
}
执行目标方法

InvocationHandler 是 JDK 动态代理的核心,织入切面,生成的代理对象的方法调用会委托到 InvocationHandler.invoke() 方法

JdkDynamicAopProxy 是 JDK 动态代理的实现类

JdkDynamicAopProxy 本身是一个 InvocationHandler,所以执行代理的某个方法时,会经过 JdkDynamicAopProxy.invoke 方法然后去调用目标方法

  • 代理对象每次执行方法首先会进入 JdkDynamicAopProxy.invoke() 方法
    • 首先会看是不是 equalshashcode 等原生方法
    • 如果是 DecoratingProxy 类和 Advised 接口的方法,都交由 proxy config 去执行,也就是 this.advised
    • 然后会通过 getInterceptorsAndDynamicInterceptionAdvice() 方法获取 拦截链,这里面包括了增强,还有他们的执行顺序
      • 如果拦截链空,则这个方法没有增强,那就 直接通过反射 执行目标对象方法,不会创建
      • 如果拦截链不空,说明要增强,就创建 MethodInvocation( 这里是 ReflectiveMethodInvocation )
        • 递归执行 所有增强器 Adivce,执行 Advice.invoke() 方法进行拦截处理,在 链的尾部 通过反射执行目标方法
        • 处理返回值
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
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Object oldProxy = null;
boolean setProxyContext = false;

TargetSource targetSource = this.advised.targetSource;
Object target = null;

try {
if (!this.equalsDefined && AopUtils.isEqualsMethod(method)) {
// The target does not implement the equals(Object) method itself.
// 如果对象没重写 equals,就返回JdkDynamicAopProxy 的 equals
return equals(args[0]);
}
else if (!this.hashCodeDefined && AopUtils.isHashCodeMethod(method)) {
// The target does not implement the hashCode() method itself.
// 如果对象没重写 hashCode,就返回JdkDynamicAopProxy 的 hashCode
return hashCode();
}
else if (method.getDeclaringClass() == DecoratingProxy.class) {
// There is only getDecoratedClass() declared -> dispatch to proxy config.
// DecoratingProxy 类和 Advised 接口的方法都交由 proxy config 去执行,也就是 this.advised
return AopProxyUtils.ultimateTargetClass(this.advised);
}
else if (!this.advised.opaque && method.getDeclaringClass().isInterface() &&
method.getDeclaringClass().isAssignableFrom(Advised.class)) {
// Service invocations on ProxyConfig with the proxy config...
return AopUtils.invokeJoinpointUsingReflection(this.advised, method, args);
}

Object retVal;

// 是否暴露代理对象,如果暴露就把当前代理对象放到 AopContext 上下文中
// 这样在本线程的其他地方也可以获取到代理对象了
if (this.advised.exposeProxy) {
// Make invocation available if necessary.
oldProxy = AopContext.setCurrentProxy(proxy);
setProxyContext = true;
}

// 通过目标源获取目标对象
target = targetSource.getTarget();
Class<?> targetClass = (target != null ? target.getClass() : null);

// 拿到这个方法的拦截链
List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);

// 如果这个方法没有增强,那就直接通过反射执行目标对象方法,不会创建 MethodInvocation
if (chain.isEmpty()) {
// We can skip creating a MethodInvocation: just invoke the target directly
// Note that the final invoker must be an InvokerInterceptor so we know it does
// nothing but a reflective operation on the target, and no hot swapping or fancy proxying.
Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);
retVal = AopUtils.invokeJoinpointUsingReflection(target, method, argsToUse);
}
// 如果拦截链不空,说明要增强,就创建 MethodInvocation( 这里是 ReflectiveMethodInvocation )
else {
// 创建方法执行器
MethodInvocation invocation =
new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain);
// 递归执行所有增强器 Adivce
// 执行 Advice.invoke() 方法进行拦截处理,在链的尾部通过反射执行目标方法
retVal = invocation.proceed();
}

// 处理返回值
Class<?> returnType = method.getReturnType();
if (retVal != null && retVal == target &&
returnType != Object.class && returnType.isInstance(proxy) &&
!RawTargetAccess.class.isAssignableFrom(method.getDeclaringClass())) {
// Special case: it returned "this" and the return type of the method
// is type-compatible. Note that we can't help if the target sets
// a reference to itself in another returned object.
retVal = proxy;
}
else if (retVal == null && returnType != Void.TYPE && returnType.isPrimitive()) {
// throw...
}
return retVal;
}
finally {
if (target != null && !targetSource.isStatic()) {
// Must have come from TargetSource.
targetSource.releaseTarget(target);
}
if (setProxyContext) {
// Restore old proxy.
AopContext.setCurrentProxy(oldProxy);
}
}
}
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
public Object proceed() throws Throwable {
// 调用完了所有的拦截链中拦截器的增强方法,直接调用目标对象的方法并退出
if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {
return invokeJoinpoint();
}

// 从拦截器链中获取拦截器
Object interceptorOrInterceptionAdvice = this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex);
// 动态匹配
if (interceptorOrInterceptionAdvice instanceof InterceptorAndDynamicMethodMatcher) {
InterceptorAndDynamicMethodMatcher dm =
(InterceptorAndDynamicMethodMatcher) interceptorOrInterceptionAdvice;
// 如果和定义的切点匹配,那么这个通知就会得到执行
if (dm.methodMatcher.matches(this.method, this.targetClass, this.arguments)) {
return dm.interceptor.invoke(this);
}
else {
// 不适用递归继续获取拦截器进行匹配、判断、调用
return proceed();
}
}
else {
// 判断出这个拦截器是一个 MethodInterceptor,则直接调用
// 动态匹配失败则直接调用
return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this);
}
}
对于 CglibProxy 来说

CglibAopProxyObjenesisCglibAopProxy 的父类

1
2
3
public ObjenesisCglibAopProxy(AdvisedSupport config) {
super(config);
}
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
public Object getProxy(@Nullable ClassLoader classLoader) {
// logger...

try {
Class<?> rootClass = this.advised.getTargetClass();
// Assert...

Class<?> proxySuperClass = rootClass;
if (rootClass.getName().contains(ClassUtils.CGLIB_CLASS_SEPARATOR)) {
proxySuperClass = rootClass.getSuperclass();
Class<?>[] additionalInterfaces = rootClass.getInterfaces();
for (Class<?> additionalInterface : additionalInterfaces) {
this.advised.addInterface(additionalInterface);
}
}

// Validate the class, writing log messages as necessary.
validateClassIfNecessary(proxySuperClass, classLoader);

// Configure CGLIB Enhancer...
Enhancer enhancer = createEnhancer();
if (classLoader != null) {
enhancer.setClassLoader(classLoader);
if (classLoader instanceof SmartClassLoader &&
((SmartClassLoader) classLoader).isClassReloadable(proxySuperClass)) {
enhancer.setUseCache(false);
}
}
enhancer.setSuperclass(proxySuperClass);
enhancer.setInterfaces(AopProxyUtils.completeProxiedInterfaces(this.advised));
enhancer.setNamingPolicy(SpringNamingPolicy.INSTANCE);
enhancer.setStrategy(new ClassLoaderAwareGeneratorStrategy(classLoader));

Callback[] callbacks = getCallbacks(rootClass);
Class<?>[] types = new Class<?>[callbacks.length];
for (int x = 0; x < types.length; x++) {
types[x] = callbacks[x].getClass();
}
// fixedInterceptorMap only populated at this point, after getCallbacks call above
enhancer.setCallbackFilter(new ProxyCallbackFilter(
this.advised.getConfigurationOnlyCopy(), this.fixedInterceptorMap, this.fixedInterceptorOffset));
enhancer.setCallbackTypes(types);

// Generate the proxy class and create a proxy instance.
// 这里创建代理对象
return createProxyClassAndInstance(enhancer, callbacks);
}
// catch...
}
执行目标方法

Cglib 动态代理执行链: 调用方法 -> 动态代理类.方法 -> MethodInterceptor.intercept 方法 -> MethodInvocation.proceed 执行增强器链 -> Adivce.invoke 方法 -> 目标方法

CglibAopProxy 会创建一个 DynamicAdvisedInterceptor 来拦截目标方法的执行

DynamicAdvisedInterceptor 实现了 MethodInterceptor

当我们执行代理的某个方法时,会经过 DynamicAdvisedInterceptor.intercept() 方法然后去调用目标方法

intercept 的步骤

  • 首先判断是否暴露代理
    • 如果暴露,就把代理放到 AopContext 中,以便在其他地方也可以拿到
  • 然后和 JDKProxy 中是一样,通过 DefaultAdvisorChainFactory 获取拦截链
    • 如果拦截链为空,同时目标方法是 public 方法的话,直接使用反射执行目标方法
    • 增强链不为空,则创建一个方法执行器 MethodInvocation( 这里创建的是 CglibMethodInvocationJDKProxy 创建的是 ReflectiveMethodInvocation )来封装增强链和目标方法,执行 MethodInvocation.proceed()
      • 因为 CglibMethodInvocationReflectiveMethodInvocation 的子类,所以后面就跟 JDKproxy 的执行一样了
    • 最后就是处理返回值
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
public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
Object oldProxy = null;
boolean setProxyContext = false;
Object target = null;
TargetSource targetSource = this.advised.getTargetSource();
try {
// 是否暴露代理对象,如果暴露就把当前代理对象放到 AopContext 上下文中,
// 这样在本线程的其他地方也可以获取到代理对象了
// 和 JDKProxy 类似
if (this.advised.exposeProxy) {
// Make invocation available if necessary.
oldProxy = AopContext.setCurrentProxy(proxy);
setProxyContext = true;
}
// Get as late as possible to minimize the time we "own" the target, in case it comes from a pool...
target = targetSource.getTarget();
Class<?> targetClass = (target != null ? target.getClass() : null);
// 一样,通过 DefaultAdvisorChainFactory 的 getInterceptorsAndDynamicInterceptionAdvice 拿到拦截链
List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
Object retVal;
// Check whether we only have one InvokerInterceptor: that is,
// no real advice, but just reflective invocation of the target.
// 如果拦截链空,且方法为 public,则这个方法没有增强,那就直接通过反射执行目标对象方法,不会创建
if (chain.isEmpty() && Modifier.isPublic(method.getModifiers())) {
Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);
retVal = methodProxy.invoke(target, argsToUse);
}
// 如果拦截链不空,说明要增强
// 创建一个方法执行器 MethodInvocation( 此处创建的是 CglibMethodInvocation )封装增强链 + 目标方法
// 执行 MethodInvocation.proceed()
// 因为 CglibMethodInvocation 是 ReflectiveMethodInvocation 的子类
// 所以后面就跟 JDKproxy 的执行一样了
else {
// We need to create a method invocation...
retVal = new CglibMethodInvocation(proxy, target, method, args, targetClass, chain, methodProxy).proceed();
}
// 处理返回值
retVal = processReturnType(proxy, target, method, retVal);
return retVal;
}
finally {
if (target != null && !targetSource.isStatic()) {
targetSource.releaseTarget(target);
}
if (setProxyContext) {
// Restore old proxy.
AopContext.setCurrentProxy(oldProxy);
}
}
}

image-20201230000214903

image-20201230000353469

区别
  • JDK动态代理
    • 利用拦截器(拦截器必须实现InvocationHanlder)加上反射机制生成一个实现代理接口的匿名类,在调用具体方法前调用InvokeHandler来处理
  • CGLIB动态代理
    • 利用ASM开源包,对代理对象类的class文件加载进来,通过修改其字节码生成子类来处理
  • 何时使用JDK还是CGLIB
    • 如果目标对象实现了接口,默认情况下会采用JDK的动态代理实现AOP
    • 如果目标对象实现了接口,可以强制使用CGLIB实现AOP
    • 如果目标对象没有实现了接口,必须采用CGLIB库,Spring会自动在JDK动态代理和CGLIB之间转换。

事务传播行为

总共 7 种

参考

image-20210613120114148

PROPAGATION_REQUIRED

所有 Propagation.REQUIRED 修饰的内部方法和外围方法均属于同一事务,只要一个方法回滚,整个事务均回滚

PROPAGATION_REQUIRES_NEW

Propagation.REQUIRES_NEW 修饰的内部方法会单独开启独立事务,且与外部方法事务独立

注意:外部方法开启了事务,内部方法抛异常,会被外部方法感知,也会回滚(try catch可以让异常不被外部感知)

PROPAGATION_NESTED

在外围方法未开启事务的情况下Propagation.NESTED和Propagation.REQUIRED作用相同,修饰的内部方法都会新开启自己的事务,且开启的事务相互独立,互不干扰

外围开启事务,内围是外围的子事务,外围回滚,内围也要回滚

外围开启事务,内围是外围的子事务,内围抛异常回滚,外围感知到,外围也回滚,包括其他子事务(同样也可以try catch拒绝感知,这样外围不会回滚,其他子事务也就不会回滚了)

等等

balabala

应用场景

注册和添加积分

注册失败,添加积分也要回滚

添加积分失败,注册不回滚