0%

spring源码(一)-BeanDefinition及其实现

BeanDefinition

spring容器中通过BeanDefinition将在xml、注解等地方的bean定义解析并存储在BeanDefinition中。我们可以通过定义一个BeanDefinition对象来表示定义了一个Bean,然后通过容器进行获取。

首先创建一个实体类:user

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
public class User {
private Integer id;

private String name;

public void init() {
System.out.println("init方法");
}

public Integer getId() {
return id;
}

public void setId(Integer id) {
this.id = id;
}

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

@Override
public String toString() {
return "User{" +
"id='" + id + '\'' +
", name='" + name + '\'' +
'}';
}
}

测试类:

1
2
3
4
5
6
7
8
9
10
11
12
@Test
public void simple(){
DefaultListableBeanFactory defaultListableBeanFactory=new DefaultListableBeanFactory();
AbstractBeanDefinition beanDefinition = BeanDefinitionBuilder.genericBeanDefinition().getBeanDefinition();
//可以设置bean的很多属性
beanDefinition.setBeanClass(User.class);
beanDefinition.setLazyInit(false);
beanDefinition.setScope("prototype");
beanDefinition.setInitMethodName("init");
defaultListableBeanFactory.registerBeanDefinition("user",beanDefinition);
System.out.println(defaultListableBeanFactory.getBean("user"));
}

通过,@Bean@Component等方式所定义的Bean,最终都会被解析为BeanDefinition对象。要理解 BeanDefinition,可以从 BeanDefinition 的继承关系开始看起:

BeanDefinition继承关系

可以看到 BeanDefinition 是一个接口,继承自 BeanMetadataElementAttributeAccessor 接口。

  • AttributeAccessor:定义用于附加和访问元数据的通用协定的接口,可以是任意对象。具体的实现则是 AttributeAccessorSupport,采用 LinkedHashMap 进行存储。
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
/**
* 定义用于附加和访问元数据的通用协定的接口,可以是任意对象。
* 具体的实现则是 AttributeAccessorSupport,采用 LinkedHashMap 进行存储。
*/
public interface AttributeAccessor {

/**
* 设置属性的值(名称唯一)
*/
void setAttribute(String name, @Nullable Object value);

/**
* 获得指定属性名称的值,如果不存在返回null
*/
@Nullable
Object getAttribute(String name);

/**
* 如果属性值为null,重新计算,返回新值,否则不应用重新计算函数,并返回已存在值
*/
@SuppressWarnings("unchecked")
default <T> T computeAttribute(String name, Function<String, T> computeFunction) {
Assert.notNull(name, "Name must not be null");
Assert.notNull(computeFunction, "Compute function must not be null");
Object value = getAttribute(name);
if (value == null) {
value = computeFunction.apply(name);
Assert.state(value != null,
() -> String.format("Compute function must not return null for attribute named '%s'", name));
setAttribute(name, value);
}
return (T) value;
}

/**
* 删除指定的name的属性,如果不存在则返回null
*/
@Nullable
Object removeAttribute(String name);

/**
* 判断指定的属性名称是否存在
*/
boolean hasAttribute(String name);

/**
* 返回所有属性的名称
*/
String[] attributeNames();

}
  • BeanMetadataElement:该接口只有一个方法 getSource,该方法返回 Bean 的来源。

这是 BeanDefinition 所继承的两个接口。接下来来看下 BeanDefinition本身。

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
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
/**
* BeanDefinition 描述了一个 bean 实例,它具有属性值、构造函数参数值以及具体实现提供的更多信息
*/
public interface BeanDefinition extends AttributeAccessor, BeanMetadataElement {

/**
* 代表是单例Bean
* @see #setScope
* @see ConfigurableBeanFactory#SCOPE_SINGLETON
*/
String SCOPE_SINGLETON = ConfigurableBeanFactory.SCOPE_SINGLETON;

/**
* Scope identifier for the standard prototype scope: {@value}.
* <p>Note that extended bean factories might support further scopes.
* 代表是原型Bean
* @see #setScope
* @see ConfigurableBeanFactory#SCOPE_PROTOTYPE
*/
String SCOPE_PROTOTYPE = ConfigurableBeanFactory.SCOPE_PROTOTYPE;



//Bean角色
int ROLE_APPLICATION = 0; //用户自定义的Bean

int ROLE_SUPPORT = 1; //来源于配置文件的Bean

int ROLE_INFRASTRUCTURE = 2; //Spring内部的Bean


// Modifiable attributes

/**
* 配置 /设置父BeanDefinition的名称 XML中的 <bean parent="">
*/
void setParentName(@Nullable String parentName);

/**
* 配置/获取父BeanDefinition的名称 XML中的 <bean parent="">
*/
@Nullable
String getParentName();

/**
* 指定此 bean 定义的 bean 类名。
* 类名可以在 bean 工厂后期处理期间修改,通常用它的解析变体替换原始类名
*/
void setBeanClassName(@Nullable String beanClassName);

/**
* 返回此 bean 定义的当前 bean 类名。
* 请注意,这不一定是运行时使用的实际类名,以防子定义覆盖/继承其父类的类名。
* 此外,这可能只是调用工厂方法的类,或者在调用方法的工厂 bean 引用的情况下它甚至可能是空的。
* 因此,不要认为这是运行时确定的 bean 类型,而只是在单个 bean 定义级别将其用于解析目的。
*/
@Nullable
String getBeanClassName();

/**
* Override the target scope of this bean, specifying a new scope name.
* @see #SCOPE_SINGLETON
* @see #SCOPE_PROTOTYPE
*/
void setScope(@Nullable String scope);

/**
* Return the name of the current target scope for this bean,
* or {@code null} if not known yet.
*/
@Nullable
String getScope();

/**
* 懒加载
*/
void setLazyInit(boolean lazyInit);

boolean isLazyInit();

/**
* 设置此 bean 初始化所依赖的 bean 的名称。 bean 工厂将保证这些 bean 首先被初始化。
*/
void setDependsOn(@Nullable String... dependsOn);

@Nullable
String[] getDependsOn();

/**
* 设置此 bean 是否是自动装配到其他 bean 的候选对象
*/
void setAutowireCandidate(boolean autowireCandidate);

boolean isAutowireCandidate();

/**
* 如果找到了多个可注入bean,那么则选择被Primary标记的bean/获取当
* //前 Bean 是否为首选的 Bean XML中的 <bean primary="">
*/
void setPrimary(boolean primary);

/**
* Return whether this bean is a primary autowire candidate.
*/
boolean isPrimary();

/**
* 配置/获取 FactoryBean 的名字 XML中的<bean factory-bean="">
*/
void setFactoryBeanName(@Nullable String factoryBeanName);

@Nullable
String getFactoryBeanName();

/**
* 配置/获取 FactoryMethod 的名字,可以是某个实例的方法(和factoryBean配合使用)
* 也可以是静态方法。 XML 中的<bean factory-method="">
*/
void setFactoryMethodName(@Nullable String factoryMethodName);

@Nullable
String getFactoryMethodName();

/**
* 返回该 Bean 构造方法的参数值
*/
ConstructorArgumentValues getConstructorArgumentValues();

/**
* 判断 getConstructorArgumentValues 是否是空对象。
* @since 5.0.2
*/
default boolean hasConstructorArgumentValues() {
return !getConstructorArgumentValues().isEmpty();
}

/**
* 获取普通属性的集合
*/
MutablePropertyValues getPropertyValues();

/**
* 判断 getPropertyValues 是否为空对象
* @since 5.0.2
*/
default boolean hasPropertyValues() {
return !getPropertyValues().isEmpty();
}

/**
* 配置/获取 Bean 的初始化方法 XML中的<bean init-method="">
* @since 5.1
*/
void setInitMethodName(@Nullable String initMethodName);

@Nullable
String getInitMethodName();

/**
* 配置/获取 Bean 的销毁方法 XML中的<bean destroy-method="">
* @since 5.1
*/
void setDestroyMethodName(@Nullable String destroyMethodName);

@Nullable
String getDestroyMethodName();

/**
* 配置/获取 Bean的角色
*/
void setRole(int role);

int getRole();

/**
* 配置/获取 Bean 的描述
*/
void setDescription(@Nullable String description);

@Nullable
String getDescription();


// Read-only attributes

/**
* 用来解析一个Bean对应的类型上的各种信息,比如泛型
*/
ResolvableType getResolvableType();

/**
* 是否为单例
*/
boolean isSingleton();

/**
* 是否为原型
*/
boolean isPrototype();

/**
* 是否抽象 XML 中的<bean abstract="true">
*/
boolean isAbstract();

/**
* 返回定义 Bean 的资源描述(便于出错时找到上下文)
*/
@Nullable
String getResourceDescription();

/**
* 如果当前 BeanDefinition 是一个代理对象,那么该方法可以用来返回原始的 BeanDefinition
*/
@Nullable
BeanDefinition getOriginatingBeanDefinition();

}

BeanDefinition实现类

BeanDefinition 是一个接口,它有多个实现类,这些实现类分别描述不同类型的 Bean。大致分为两种:

  • 抽象实现:AbstractBeanDefinition

  • 子接口:AnnotatedBeanDefinition

image-20220819163957558

继承关系如下:

image-20220819164206490

删除掉了ClassDerivedBeanDefinition这个内部类,形成上面类图

抽象实现:AbstractBeanDefinition

AbstractBeanDefinition 是一个抽象类,BeanDefinition 中只是定义了一系列的 get/set 方法,并没有提供对应的属性,在 AbstractBeanDefinition 中将所有的属性定义出来了。该抽象类下有个三个子类:GenericBeanDefinitionRootBeanDefinitionChildBeanDefinition。我们先来看 AbstractBeanDefinition本身的一些方法与属性。

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
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
/**
* 具体的、成熟的BeanDefinition类的基类,分解出GenericBeanDefinition 、 RootBeanDefinition和ChildBeanDefinition的公共属性。
* autowire 常量与AutowireCapableBeanFactory接口中定义的常量相匹配
*
* @see GenericBeanDefinition
* @see RootBeanDefinition
* @see ChildBeanDefinition
*/
@SuppressWarnings("serial")
public abstract class AbstractBeanDefinition extends BeanMetadataAttributeAccessor
implements BeanDefinition, Cloneable {

/**
* 默认作用域名称的常量:等效于单例
*/
public static final String SCOPE_DEFAULT = "";

/**
* 自动装配的一些常量
* autowireMode = 0,默认值,未激活Autowiring。
* bean 标签的 autowire 属性值为 no
* 1、在xml中需要手动指定依赖注入对象 配置 property标签或者 constructor-arg标签
* 2、使用 @Autowired 注解,autowireMode 的值也是 0
*
* @see #setAutowireMode
*/
public static final int AUTOWIRE_NO = AutowireCapableBeanFactory.AUTOWIRE_NO;

/**
* autowireMode = 1,根据set方法的的名称作为Bean名称进行依赖查找
* (去掉set,并尝试将首字母变为小写),并将对象设置到该set方法的参数上
* bean 标签的 autowire 属性值配置为 byName
*
* @see #setAutowireMode
*/
public static final int AUTOWIRE_BY_NAME = AutowireCapableBeanFactory.AUTOWIRE_BY_NAME;

/**
* autowireMode = 2,根据set方法参数的类型作为Bean类型进行依赖查找
* 并将对象设置到该set方法的参数上
* bean 标签的 autowire 属性值配置为 byType
*
* @see #setAutowireMode
*/
public static final int AUTOWIRE_BY_TYPE = AutowireCapableBeanFactory.AUTOWIRE_BY_TYPE;

/**
* autowireMode = 3,构造器注入
*
* @see #setAutowireMode
*/
public static final int AUTOWIRE_CONSTRUCTOR = AutowireCapableBeanFactory.AUTOWIRE_CONSTRUCTOR;

/**
* 表明通过Bean的class的内部来自动装配 Spring3.0被弃用。
* bean 标签的 autowire 属性值配置为 autodetect
*
* @see #setAutowireMode
* @deprecated as of Spring 3.0: If you are using mixed autowiring strategies,
* use annotation-based autowiring for clearer demarcation of autowiring needs.
*/
@Deprecated
public static final int AUTOWIRE_AUTODETECT = AutowireCapableBeanFactory.AUTOWIRE_AUTODETECT;

/**
* 检查依赖是否合法,在本类中,默认不进行依赖检查 不进行检查
*
* @see #setDependencyCheck
*/
public static final int DEPENDENCY_CHECK_NONE = 0;

/**
* /对对象引用进行依赖性检查
*
* @see #setDependencyCheck
*/
public static final int DEPENDENCY_CHECK_OBJECTS = 1;

/**
* 对“简单”属性进行依赖性检查
*
* @see #setDependencyCheck
* @see org.springframework.beans.BeanUtils#isSimpleProperty
*/
public static final int DEPENDENCY_CHECK_SIMPLE = 2;

/**
* 对所有属性进行依赖检查
* (object references as well as "simple" properties).
*
* @see #setDependencyCheck
*/
public static final int DEPENDENCY_CHECK_ALL = 3;

/**
* 若Bean未指定销毁方法,容器应该尝试推断Bean的销毁方法的名字,
* 目前,推断的销毁方法的名字一般为close或是shutdown
*/
public static final String INFER_METHOD = "(inferred)";


//Bean的class对象或是类的全限定名
@Nullable
private volatile Object beanClass;

//默认的scope是单例,对应bean属性scope
//@scope
@Nullable
private String scope = SCOPE_DEFAULT;

//是否是抽象,对应bean属性abstract
private boolean abstractFlag = false;

//是否延迟加载 对应bean属性lazy-init,默认不是懒加载
//@lazy
@Nullable
private Boolean lazyInit;

//自动注入模式,对应bean属性autowire,默认不进行自动装配
private int autowireMode = AUTOWIRE_NO;

//是否进行依赖检查,默认不进行依赖检查
private int dependencyCheck = DEPENDENCY_CHECK_NONE;

//用来表示一个bean的实例化是否依靠另一个bean的实例化,先加载dependsOn的bean,
//对应bean属性depend-on
//@DependsOn
@Nullable
private String[] dependsOn;

/**
* autowire-candidate属性设置为false,这样容器在查找自动装配对象时,
* 将不考虑该bean,即它不会被考虑作为其他bean自动装配的候选者,
* 但是该bean本身还是可以使用自动装配来注入其他bean的
*/
private boolean autowireCandidate = true;

/**
* 自动装配时出现多个bean候选者时,将作为首选者,对应bean属性primary,默认不是首选的
*
* @Primary
*/
private boolean primary = false;

/**
* 用于记录Qualifier,对应子元素qualifier <bean><qualifier></qualifier></bean>
* 如果容器中有多个相同类型的 bean,这时我们就可以使用qualifier属性来设置加载指定Bean名称的bean
* @Qualifier
*/
private final Map<String, AutowireCandidateQualifier> qualifiers = new LinkedHashMap<>();

//java8的函数式接口,创建bean实例的方式之一
@Nullable
private Supplier<?> instanceSupplier;

//是否允许访问非public方法和属性, 默认是true
private boolean nonPublicAccessAllowed = true;

/**
* 是否以一种宽松的模式解析构造函数,默认为true,
* 如果为false,则在以下情况
* interface ITest{}
* class ITestImpl implements ITest{};
* class Main {
* Main(ITest i) {}
* Main(ITestImpl i) {}
* }
* 抛出异常,因为Spring无法准确定位哪个构造函数程序设置
*/
private boolean lenientConstructorResolution = true;

//工厂类名,对应bean属性factory-bean
@Nullable
private String factoryBeanName;

//工厂方法名,对应bean属性factory-method
@Nullable
private String factoryMethodName;

//记录构造函数注入属性,对应bean属性constructor-arg
@Nullable
private ConstructorArgumentValues constructorArgumentValues;

//Bean属性的名称以及对应的值,这里不会存放构造函数相关的参数值,只会存放通过setter注入的值
@Nullable
private MutablePropertyValues propertyValues;

//方法重写的持有者,记录lookup-method、replaced-method元素 @Lookup
private MethodOverrides methodOverrides = new MethodOverrides();

//初始化方法,对应bean属性init-method
@Nullable
private String initMethodName;

//销毁方法,对应bean属性destroy-method
@Nullable
private String destroyMethodName;

//是否执行init-method,默认为true
private boolean enforceInitMethod = true;

//是否执行destroy-method,默认为true
private boolean enforceDestroyMethod = true;

//是否是用户定义的而不是应用程序本身定义的,创建AOP时候为true
private boolean synthetic = false;

//Bean的角色,为用户自定义Bean
private int role = BeanDefinition.ROLE_APPLICATION;

//Bean的描述信息
@Nullable
private String description;

//这个bean定义的资源
@Nullable
private Resource resource;

}

RootBeanDefinition

BeanDefinition 是可以分层级的,因为有ParentNamegetter/setter。这个在进行 BeanDefinition 的配置时更加灵活,也可以进行配置的复用;但是在 Bean 实例构建时就很难受了,我构建一个 Bean 还有递归的去父类找配置。。。

所以我们想出了一个解决方法——在构建 Bean 实例时,先把 BeanDefinition 拍平,这样所有的配置就都在一个BeanDefinition中了。这就是RootBeanDefinition的主要使用场景,在这种场景下因为是拍平的,所以变量名一般叫 mergedBeanDefinition或者mbd

注意:

RootBeanDefinition中在AbstractBeanDefinition的基础上增加了很多的实例属性以方便使用。当然,两者各有侧重点:

  • AbstractBeanDefinition:是对通用功能的扩展,是为了兼顾 BD梳理和Bean实例化两个场景的。所以主要是一些属性的扩展和对属性的标记(标记捷径)
  • RootBeanDefinition:主要在 Bean 实例化时使用,为了方便实例化操作,提供了大量的缓存字段,方便重复实例化时减少工作量。

源码:

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
public class RootBeanDefinition extends AbstractBeanDefinition {

// BeanDefinitionHolder 存储 Bean 的名称、别名、BeanDefinition
@Nullable
private BeanDefinitionHolder decoratedDefinition;

// AnnotatedElement 是java反射包的接口,通过它可以查看 Bean 的注解信息
@Nullable
private AnnotatedElement qualifiedElement;

// 决定了什么时候 BeanDefinition 需要重新合并
volatile boolean stale;

// 允许缓存
boolean allowCaching = true;

// 工厂方法是否唯一
boolean isFactoryMethodUnique;

//封装了 java.lang.reflect.Type,提供了泛型相关的操作
@Nullable
volatile ResolvableType targetType;

//用于缓存给定bean定义中确定的类
// 表示 RootBeanDefinition 存储哪个类的信息
@Nullable
volatile Class<?> resolvedTargetType;

//如果bean是FactoryBean,则用于缓存
@Nullable
volatile Boolean isFactoryBean;

//用于缓存泛型类型工厂方法的返回类型
@Nullable
volatile ResolvableType factoryMethodReturnType;

//用于缓存唯一的工厂方法
@Nullable
volatile Method factoryMethodToIntrospect;

//用于缓存已解析的销毁方法名称(也用于推断)
@Nullable
volatile String resolvedDestroyMethodName;

//下面四个构造函数字段的公共锁
final Object constructorArgumentLock = new Object();

// 用于缓存已解析的构造函数或工厂方法
@Nullable
Executable resolvedConstructorOrFactoryMethod;

//将构造函数参数标记为已解析
boolean constructorArgumentsResolved = false;

//用于缓存完全解析的构造函数参数
@Nullable
Object[] resolvedConstructorArguments;

//用于缓存部分准备好的构造函数参数
@Nullable
Object[] preparedConstructorArguments;

//下面两个后处理字段的通用锁
final Object postProcessingLock = new Object();

//这表明已经应用了MergedBeanDefinitionPostProcessor
boolean postProcessed = false;

//表明一个实例化前的后处理器已经启动
@Nullable
volatile Boolean beforeInstantiationResolved;

//实际缓存的类型是 Constructor、Field、Method 类型
@Nullable
private Set<Member> externallyManagedConfigMembers;


// InitializingBean中 的 init 回调函数名 afterPropertiesSet 会在这里记录,以便进行生命周期回调
@Nullable
private Set<String> externallyManagedInitMethods;

// DisposableBean 的 destroy 回调函数名 destroy 会在这里记录,以便进生命周期回调
@Nullable
private Set<String> externallyManagedDestroyMethods;

}

例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
@Test
public void rootBeanDefinitionTest(){
//容器
DefaultListableBeanFactory context = new DefaultListableBeanFactory();
//属性的集合 在其父类 AbstractBeanDefinition 已经提到过了
MutablePropertyValues mpvs = new MutablePropertyValues();
mpvs.add("id",4);
mpvs.add("name","gongj");
//BeanDefinition
RootBeanDefinition rootBeanDefinition =new RootBeanDefinition(User.class,null,mpvs);
//注册到Spring容器中
context.registerBeanDefinition("user",rootBeanDefinition);
User user=(User)context.getBean("user");
System.out.println(user);
}

ChildBeanDefinition

该类继承自 AbstractBeanDefinition。其相当于一个子类,不可以单独存在,必须依赖一个父 BeanDetintion,构造 ChildBeanDefinition 时,通过构造方法传入父 BeanDetintion 的名称或通过 setParentName 设置父名称。它可以从父类继承方法参数、属性值,并可以重写父类的方法,同时也可以增加新的属性或者方法。

增加了 parentName,指向父 BD 。已弃用,参考 GenericBeanDefinition

例子:

新建Person类,在User类的基础上增加一个address属性

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
public class Person {
private Integer id;

private String name;

private String address;

public void setId(Integer id) {
this.id = id;
}

public Integer getId() {
return id;
}

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

public String getAddress() {
return address;
}

public void setAddress(String address) {
this.address = address;
}

@Override
public String toString() {
return "Person{" +
"id='" + id + '\'' +
", name='" + name + '\'' +
", address='" + address + '\'' +
'}';
}
}

测试方法:

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
@Test
public void childDefinitionTest(){
//容器
DefaultListableBeanFactory context = new DefaultListableBeanFactory();
//普通属性的集合 在其父类 AbstractBeanDefinition 已经提到过了
MutablePropertyValues mpvs = new MutablePropertyValues();
mpvs.add("id",4);
mpvs.add("name","gongj");
//RootBeanDefinition
RootBeanDefinition rootBeanDefinition = new RootBeanDefinition(User.class,null,mpvs);
//注册到Spring容器中
context.registerBeanDefinition("user",rootBeanDefinition);

// ChildBeanDefinition 开始
MutablePropertyValues childValues = new MutablePropertyValues();
childValues.add("address","上海市");
//通过构造方法传入父 BeanDetintion 的名称
ChildBeanDefinition childBeanDefinition = new ChildBeanDefinition("user", Person.class,null,childValues);
//注册
context.registerBeanDefinition("person", childBeanDefinition);
User user = context.getBean(User.class);
Person person = context.getBean(Person.class);
System.out.println("user = " + user);
System.out.println("person = " + person);
}

GenericBeanDefinition

GenericBeanDefinition 是从 Spring2.5 以后新加入的 bean 文件配置属性定义类,是一站式服务类。GenericBeanDefinition 可以动态设置父 Bean,同时兼具 RootBeanDefinitionChildBeanDefinition 的功能。

GenericBeanDefinition 的实现比较简单,在 AbstractBeanDefinition 的基础上只增加了parentName的功能,其余的实现都在父类 AbstractBeanDefinition 里。

注:若你是xml配置,会解析所有属性并统一封装至 GenericBeanDefinition 类型的实例中,之后再逐渐解析的。

源码

1
2
3
4
5
6
public class GenericBeanDefinition extends AbstractBeanDefinition {

// 父bean的名称
@Nullable
private String parentName;
}

例子

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
@Test
public void genericBeanDefinitionTest(){
//容器
DefaultListableBeanFactory ctx = new DefaultListableBeanFactory();
//普通属性的集合 在其父类 AbstractBeanDefinition 已经提到过了
MutablePropertyValues mpvs = new MutablePropertyValues();
mpvs.add("id",4);
mpvs.add("name","gongj");
GenericBeanDefinition parentGenericBeanDefinition = new GenericBeanDefinition();
parentGenericBeanDefinition.setBeanClass(User.class);
parentGenericBeanDefinition.setPropertyValues(mpvs);
//注册到Spring容器中
ctx.registerBeanDefinition("user",parentGenericBeanDefinition);

GenericBeanDefinition childGenericBeanDefinition = new GenericBeanDefinition();
//设置父BeanDefinition的名称
childGenericBeanDefinition.setParentName("user");
childGenericBeanDefinition.setBeanClass(Person.class);
childGenericBeanDefinition.getPropertyValues().add("address", "上海市");
//注册到Spring容器中
ctx.registerBeanDefinition("person", childGenericBeanDefinition);
User user = ctx.getBean(User.class);
Person person = ctx.getBean(Person.class);
System.out.println("user = " + user);
System.out.println("person = " + person);
}

子接口:AnnotatedBeanDefinition

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public interface AnnotatedBeanDefinition extends BeanDefinition {

/**
* 获取此bean定义注解的元数据
*/
AnnotationMetadata getMetadata();

/**
* 获取此bean定义的工厂方法的元数据,如果没有,则为null
*/
@Nullable
MethodMetadata getFactoryMethodMetadata();

}

该接口可以返回两个元数据的类:

  • AnnotationMetadata:主要对 Bean 的注解信息进行操作,如:获取当前 Bean 标注的所有注解、判断是否包含指定注解。
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
/**
* 主要对 Bean 的注解信息进行操作,如:获取当前 Bean 标注的所有注解、判断是否包含指定注解。
* @since 2.5
* @see StandardAnnotationMetadata
* @see org.springframework.core.type.classreading.MetadataReader#getAnnotationMetadata()
* @see AnnotatedTypeMetadata
*/
public interface AnnotationMetadata extends ClassMetadata, AnnotatedTypeMetadata {

/**
* 获取所有注解完全限定类名
* @return the annotation type names
*/
default Set<String> getAnnotationTypes() {
return getAnnotations().stream()
.filter(MergedAnnotation::isDirectlyPresent)
.map(annotation -> annotation.getType().getName())
.collect(Collectors.toCollection(LinkedHashSet::new));
}

/**
* 获得annottationName对应的元注解的类全限定名
* @return the meta-annotation type names, or an empty set if none found
*/
default Set<String> getMetaAnnotationTypes(String annotationName) {
MergedAnnotation<?> annotation = getAnnotations().get(annotationName, MergedAnnotation::isDirectlyPresent);
if (!annotation.isPresent()) {
return Collections.emptySet();
}
return MergedAnnotations.from(annotation.getType(), SearchStrategy.INHERITED_ANNOTATIONS).stream()
.map(mergedAnnotation -> mergedAnnotation.getType().getName())
.collect(Collectors.toCollection(LinkedHashSet::new));
}

/**
* 是否包含指定注解
* @return {@code true} if a matching annotation is present
*/
default boolean hasAnnotation(String annotationName) {
return getAnnotations().isDirectlyPresent(annotationName);
}

/**
* 确定是否含有某个元注解
* @return {@code true} if a matching meta-annotation is present
*/
default boolean hasMetaAnnotation(String metaAnnotationName) {
return getAnnotations().get(metaAnnotationName,
MergedAnnotation::isMetaPresent).isPresent();
}

/**
* 类里面只要有一个方法标注有指定注解,就返回true
*/
default boolean hasAnnotatedMethods(String annotationName) {
return !getAnnotatedMethods(annotationName).isEmpty();
}

/**
* 返回所有的标注有指定注解的方法元信息
*/
Set<MethodMetadata> getAnnotatedMethods(String annotationName);


/**
* 工厂方法来使用标准反射为给定的类创建一个新的AnnotationMetadata实例
*/
static AnnotationMetadata introspect(Class<?> type) {
return StandardAnnotationMetadata.from(type);
}

}

  • MethodMetadata:方法的元数据类。提供获取方法名称、此方法所属类的全类名、是否是抽象方法、判断是否是静态方法、判断是否是final方法等。
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
/**
* 方法的元数据类。提供获取方法名称、此方法所属类的全类名、是否是抽象方法、判断是否是静态方法、判断是否是final方法等。
*/
public interface MethodMetadata extends AnnotatedTypeMetadata {

/**
* 返回方法的名字
*/
String getMethodName();

/**
* 返回该方法所属的类的全限定名
*/
String getDeclaringClassName();

/**
* 返回该方法返回类型的全限定名
*/
String getReturnTypeName();

/**
* 方法是否是有效的抽象方法:即在类上标记为抽象的或声明为规则的,
* 接口中的非默认方法。
*/
boolean isAbstract();

/**
* 方法是否声明为'static'。
*/
boolean isStatic();

/**
* 方法是否标记为'final'。
*/
boolean isFinal();

/**
* 方法是否可重写:即没有标记为static、final或private。
*/
boolean isOverridable();

}

该接口下有三大子类: ScannedGenericBeanDefinitionConfigurationClassBeanDefinitionAnnotatedGenericBeanDefinition

ScannedGenericBeanDefinition

实现了 AnnotatedBeanDefinition 也继承了 GenericBeanDefinition。这个 BeanDefinition 用来描述标注@Component、@Service、@Controller等注解标记的类会解析为 ScannedGenericBeanDefinition

它的源码很简单,就是多了一个属性:metadata 用来存储扫描进来的Bean的一些注解信息

源码

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
public class ScannedGenericBeanDefinition extends GenericBeanDefinition implements AnnotatedBeanDefinition {

//用来存储扫描进来的Bean的一些注解信息。
private final AnnotationMetadata metadata;


/**
* Create a new ScannedGenericBeanDefinition for the class that the
* given MetadataReader describes.
* @param metadataReader the MetadataReader for the scanned target class
*/
public ScannedGenericBeanDefinition(MetadataReader metadataReader) {
Assert.notNull(metadataReader, "MetadataReader must not be null");
this.metadata = metadataReader.getAnnotationMetadata();
setBeanClassName(this.metadata.getClassName());
setResource(metadataReader.getResource());
}


@Override
public final AnnotationMetadata getMetadata() {
return this.metadata;
}

@Override
@Nullable
public MethodMetadata getFactoryMethodMetadata() {
return null;
}

}

例子

新建AppConfig类,用来扫描@Compent等注解

1
2
3
@ComponentScan(basePackages ={"com.wch.study.spring"} )
public class AppConfig {
}

新建IndexController类,添加@Controller注解

1
2
3
4
@Controller
public class IndexController {
}

测试:

1
2
3
4
5
6
@Test
public void scannedGenericBeanDefinitionTest(){
AnnotationConfigApplicationContext configApplicationContext=new AnnotationConfigApplicationContext(AppConfig.class);
BeanDefinition indexController = configApplicationContext.getBeanFactory().getBeanDefinition("indexController");
System.out.println(indexController.getClass());
}

ConfigurationClassBeanDefinition

该类继承自 GenericBeanDefinition ,并实现了AnnotatedBeanDefinition 接口。这个 BeanDefinition 用来描述标注使用了 @Configuration 注解标记配置类会解析为 AnnotatedGenericBeanDefinition

源码

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
/**
* 该类继承自 GenericBeanDefinition ,并实现了AnnotatedBeanDefinition 接口。
* 这个 BeanDefinition 用来描述标注使用了 @Configuration 注解标记配置类会解析为 AnnotatedGenericBeanDefinition。
*
*/
@SuppressWarnings("serial")
public class AnnotatedGenericBeanDefinition extends GenericBeanDefinition implements AnnotatedBeanDefinition {

// 注解元数据
private final AnnotationMetadata metadata;

@Nullable
private MethodMetadata factoryMethodMetadata;


/**
* 为给定的bean类创建一个新的AnnotatedGenericBeanDefinition
* @param beanClass the loaded bean class:加载的bean类
*/
public AnnotatedGenericBeanDefinition(Class<?> beanClass) {
setBeanClass(beanClass);
// 当前类上有哪些注解
this.metadata = AnnotationMetadata.introspect(beanClass);
}

/**
* 为给定的注释元数据创建一个新AnnotatedGenericBeanDefinition,传入AnnotationMetadata
* @since 3.1.1
*/
public AnnotatedGenericBeanDefinition(AnnotationMetadata metadata) {
Assert.notNull(metadata, "AnnotationMetadata must not be null");
if (metadata instanceof StandardAnnotationMetadata) {
setBeanClass(((StandardAnnotationMetadata) metadata).getIntrospectedClass());
}
else {
setBeanClassName(metadata.getClassName());
}
this.metadata = metadata;
}

/**
* 基于一个带注解的类和该类上的工厂方法。,为给定的注释元数据创建一个新的AnnotatedGenericBeanDefinition,
*/
public AnnotatedGenericBeanDefinition(AnnotationMetadata metadata, MethodMetadata factoryMethodMetadata) {
this(metadata);
Assert.notNull(factoryMethodMetadata, "MethodMetadata must not be null");
setFactoryMethodName(factoryMethodMetadata.getMethodName());
this.factoryMethodMetadata = factoryMethodMetadata;
}


@Override
public final AnnotationMetadata getMetadata() {
return this.metadata;
}

@Override
@Nullable
public final MethodMetadata getFactoryMethodMetadata() {
return this.factoryMethodMetadata;
}

}

例子

新建Myconfig类,增加@Configuration注解

1
2
3
4
5
@Configuration
public class MyConfig {


}
1
2
3
4
5
6
@Test
public void annotatedGenericBeanDefinitionTest(){
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(MyConfig.class);
BeanDefinition myConfig = context.getBeanFactory().getBeanDefinition("myConfig");
System.out.println(myConfig.getClass());
}

ConfigurationClassBeanDefinition

它是ConfigurationClassBeanDefinitionReader的一个私有的静态内部类:这个类负责将@Bean注解的方法转换为对应的ConfigurationClassBeanDefinition 类,源码就不过多解释了,和之前几个BeanDefinition差不多。

其功能特点如下:

  • 1、如果 @Bean 注解没有指定 Bean 的名字,默认会用方法的名字作为Bean的名称。
  • 2、标注 @Configuration、@Component、@Service 注解的类会成为一个工厂类,而标注 @Bean 注解的方法会成为工厂方法,通过工厂方法实例化 Bean。

例子

在MyConfig类新增方法

1
2
3
4
@Bean("qq")
public User myUserBean(){
return new User();
}

测试

1
2
3
4
5
6
@Test
public void configurationClassBeanDefinitionTest(){
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(MyConfig.class);
BeanDefinition qq = context.getBeanFactory().getBeanDefinition("qq");
System.out.println(qq.getClass());
}

spring初始化时,会用GenericBeanDefinition或是ConfigurationClassBeanDefinition(用@Bean注解注释的类)存储用户自定义的Bean,在初始化Bean时,又会将其转换为RootBeanDefinition。