BeanDefinition
一.知识储备
MetadataReader
是 Spring 提供的一个接口,用于读取类的元数据信息。它可以用于扫描类文件,获取类的基本信息,如类名、类的注解等。在注解驱动的开发中,`MetadataReader` 通常用于扫描包中的类,并从这些类中提取注解信息,以便配置 Spring Bean。[点击查看](https://github.com/xuchengsheng/spring-reading/tree/master/spring-metadata/spring-metadata-metadataReader)
AnnotationMetadata
接口中的 introspect
方法用于深入分析类的注解信息。它可以帮助我们获取类上的注解、类的方法上的注解、类的字段上的注解等。在 Spring 中,`introspect` 方法通常用于解析被 @Component
, @Configuration
和其他注解标记的类,以确定它们如何被实例化并配置为 Spring Bean
二、基本描述
BeanDefinition
是 Spring 框架中的关键构建块,它是一种配置元数据,用于详细描述和定义应用程序中的 Bean 对象,包括 Bean 的类名、作用域、依赖关系、构造函数参数、属性值、初始化方法、销毁方法等信息,从而允许 Spring 容器准确地实例化、配置和管理这些 Bean。通过`BeanDefinition`,我们可以灵活地配置应用程序中的组件,使其能够实现依赖注入、AOP 切面、作用域控制等核心功能,促进松耦合、可维护和可扩展的应用程序开发。
三、主要功能
1. 定义 Bean 的类
用于指定要实例化的 Bean 的类名。它告诉 Spring 容器要创建哪个 Java 类的对象。
2. 定义 Bean 的作用域
允许我们指定 Bean 的作用域,例如 singleton(单例)或 prototype(多例)。这影响了 Bean 在容器中的生命周期。
3. 构造函数参数和属性值
允许我们指定 Bean 的构造函数参数和属性值,以便在实例化 Bean 时传递参数或设置属性。
4. 定义初始化和销毁方法
定义 Bean 的初始化方法和销毁方法,以确保在 Bean 创建和销毁时执行特定的逻辑。
5. Bean 的延迟初始化
允许我们设置 Bean 是否延迟初始化,即在第一次请求时创建 Bean 实例。
6. 依赖关系
允许我们指定 Bean 之间的依赖关系,以确保在创建 Bean 时正确注入依赖的其他 Bean。
7. 描述 Bean 的角色
允许我们为 Bean 指定一个角色(role),通常包括应用程序 Bean、基础设施 Bean、测试 Bean 等。
8. Bean 的属性覆盖
允许我们使用属性覆盖机制,通过不同的配置源(如属性文件或环境变量)覆盖已定义的属性值。
9. Bean 的注解和元数据
可以包含关于 Bean 的注解信息和元数据,这对于处理注解驱动的开发非常有用。
10. 动态创建和注册 Bean
允许我们在运行时动态创建和注册 Bean,而不仅仅是静态配置。
四、接口源码
从`BeanDefinition` 接口源码来看,它描述和配置 Spring 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 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 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497
|
public interface BeanDefinition extends AttributeAccessor, BeanMetadataElement {
String SCOPE_SINGLETON = ConfigurableBeanFactory.SCOPE_SINGLETON;
String SCOPE_PROTOTYPE = ConfigurableBeanFactory.SCOPE_PROTOTYPE;
int ROLE_APPLICATION = 0;
int ROLE_SUPPORT = 1;
int ROLE_INFRASTRUCTURE = 2;
void setParentName(@Nullable String parentName);
@Nullable
String getParentName();
void setBeanClassName(@Nullable String beanClassName);
@Nullable
String getBeanClassName();
void setScope(@Nullable String scope);
@Nullable
String getScope();
void setLazyInit(boolean lazyInit);
boolean isLazyInit();
void setDependsOn(@Nullable String... dependsOn);
@Nullable
String[] getDependsOn();
void setAutowireCandidate(boolean autowireCandidate);
boolean isAutowireCandidate();
void setPrimary(boolean primary);
boolean isPrimary();
void setFactoryBeanName(@Nullable String factoryBeanName);
@Nullable
String getFactoryBeanName();
void setFactoryMethodName(@Nullable String factoryMethodName);
@Nullable
String getFactoryMethodName();
ConstructorArgumentValues getConstructorArgumentValues();
default boolean hasConstructorArgumentValues() {
return !getConstructorArgumentValues().isEmpty();
}
MutablePropertyValues getPropertyValues();
default boolean hasPropertyValues() {
return !getPropertyValues().isEmpty();
}
void setInitMethodName(@Nullable String initMethodName);
@Nullable
String getInitMethodName();
void setDestroyMethodName(@Nullable String destroyMethodName);
@Nullable
String getDestroyMethodName();
void setRole(int role);
int getRole();
void setDescription(@Nullable String description);
@Nullable
String getDescription();
ResolvableType getResolvableType();
boolean isSingleton();
boolean isPrototype();
boolean isAbstract();
@Nullable
String getResourceDescription();
@Nullable
BeanDefinition getOriginatingBeanDefinition();
}
|
五、主要实现
1. GenericBeanDefinition
描述通用的 Bean 定义,可以用于大多数类型的 Bean。
具有灵活的属性配置,可以设置类名、作用域、初始化和销毁方法、构造函数参数、属性值等。
通常用于手动配置 Bean 或需要自定义 Bean 定义的情况。
2. RootBeanDefinition
3. ChildBeanDefinition
4. AnnotatedGenericBeanDefinition
5. ConfigurationClassBeanDefinition
用于表示配置类(`@Configuration` 注解)的 Bean 定义,通常用于 Spring 配置。
表示配置类作为 Bean 定义,支持包含其他 Bean 定义的配置类。
通常由 Spring 容器自动创建,以支持 @Configuration
注解的配置。
6. ScannedGenericBeanDefinition
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
| classDiagram
direction BT
class BeanDefinition {
<<interface>>
}
class AnnotatedBeanDefinition {
<<interface>>
}
class AbstractBeanDefinition {
<<Abstract>>
}
class GenericBeanDefinition {
}
class RootBeanDefinition {
}
class ChildBeanDefinition {
}
class AnnotatedGenericBeanDefinition {
}
class ScannedGenericBeanDefinition {
}
class ConfigurationClassBeanDefinition {
}
AnnotatedBeanDefinition ..|> BeanDefinition
AbstractBeanDefinition --|> BeanDefinition
GenericBeanDefinition ..|> AbstractBeanDefinition
RootBeanDefinition ..|> AbstractBeanDefinition
ChildBeanDefinition ..|> AbstractBeanDefinition
AnnotatedGenericBeanDefinition ..|> GenericBeanDefinition
ScannedGenericBeanDefinition ..|> GenericBeanDefinition
ConfigurationClassBeanDefinition ..|> RootBeanDefinition
|
六、最佳实践
创建了一个Spring容器(`DefaultListableBeanFactory`),然后通过`createBeanDefinition()`方法创建并配置了一个自定义的Bean定义(`ScannedGenericBeanDefinition`),包括作用域、初始化方法、销毁方法、属性值等。接着,它注册这个Bean定义到容器中,并使用容器获取Bean实例,打印出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
| public class BeanDefinitionDemo {
public static void main(String[] args) throws Exception {
DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
beanFactory.registerBeanDefinition("myBean", createBeanDefinition());
MyBean myChildBean = beanFactory.getBean("myBean", MyBean.class);
System.out.println("MyBean = " + myChildBean);
beanFactory.destroySingleton("myBean");
}
private static BeanDefinition createBeanDefinition() throws IOException {
SimpleMetadataReaderFactory metadataReaderFactory = new SimpleMetadataReaderFactory();
MetadataReader metadataReader = metadataReaderFactory.getMetadataReader(MyBean.class.getName());
ScannedGenericBeanDefinition beanDefinition = new ScannedGenericBeanDefinition(metadataReader);
beanDefinition.setScope("singleton");
beanDefinition.setLazyInit(true);
beanDefinition.setPrimary(true);
beanDefinition.setAbstract(false);
beanDefinition.setInitMethodName("init");
beanDefinition.setDestroyMethodName("destroy");
beanDefinition.setAutowireCandidate(true);
beanDefinition.setRole(BeanDefinition.ROLE_APPLICATION);
beanDefinition.setDescription("This is a custom bean definition");
beanDefinition.setResourceDescription("com.xcs.spring.BeanDefinitionDemo");
beanDefinition.getPropertyValues().add("name", "lex");
beanDefinition.getPropertyValues().add("age", "18");
return 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
| MyBean 的Java类,代表了一个简单的Java Bean。
public class MyBean {
private String name;
private String age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getAge() {
return age;
}
public void setAge(String age) {
this.age = age;
}
public void init(){
System.out.println("execute com.xcs.spring.bean.MyBean.init");
}
public void destroy(){
System.out.println("execute com.xcs.spring.bean.MyBean.destroy");
}
@Override
public String toString() {
return "MyBean{" +
"name='" + name + '\'' +
", age='" + age + '\'' +
'}';
}
}
|
运行结果发现,与`BeanDefinition`配置相关,初始化方法和销毁方法的调用以及属性值的设置受`BeanDefinition`中相应的配置项影响,`BeanDefinition`用于定义和配置Bean的元信息,使Spring容器可以正确管理Bean的生命周期和属性。
1 2 3 4 5
| execute com.xcs.spring.bean.MyBean.init
MyBean = MyBean{name='lex', age='18'}
execute com.xcs.spring.bean.MyBean.destroy
|
七、与其他组件的关系
1. DefaultListableBeanFactory
负责管理Bean的创建、初始化和销毁,而BeanDefinition提供了描述Bean的元信息的方式,DefaultListableBeanFactory使用BeanDefinition来创建和管理Bean实例
2. BeanPostProcessor
拦截Bean初始化过程的接口,它可以在Bean创建后、初始化前后对Bean进行处理。BeanDefinition的信息可以在BeanPostProcessor中使用,例如在初始化前修改Bean的属性值。
3. BeanDefinitionRegistry
注册和管理BeanDefinition的接口,定义了BeanDefinition的注册和访问方法。BeanFactory和ApplicationContext实现了BeanDefinitionRegistry接口,通过它们可以注册和获取BeanDefinition。
4. BeanDefinitionReader
从外部配置文件(如`XML、YAML、Properties`文件)中读取BeanDefinition的工具。它将外部配置信息解析成BeanDefinition并注册到`BeanFactory`中。
八、常见问题
1. BeanDefinition的作用是什么?
主要作用是定义和配置Bean的属性和行为,以便Spring容器可以根据这些信息动态地创建、初始化和管理Bean实例。
2. BeanDefinition的生命周期是怎样的?
生命周期与Spring容器相同,它在容器启动时进行注册和解析,然后被用于创建和管理Bean实例的生命周期。
3. BeanDefinition如何注册?
通过BeanDefinitionRegistry接口的实现类(如DefaultListableBeanFactory)进行注册,或者通过BeanDefinitionReader从外部配置文件中加载并注册。
4. BeanDefinition的属性有哪些?
属性包括Bean的类名、作用域、初始化方法、销毁方法、属性值等。具体属性取决于Bean的配置需求。
5. BeanDefinition如何修改?
可以在注册后通过编程方式进行修改,例如更改属性值、作用域、初始化方法、销毁方法等。
6. BeanDefinition的作用域有哪些?
包括Singleton(单例)、Prototype(原型)、Request(请求)、Session(会话)、等等,可以根据需求选择合适的作用域。
7. BeanDefinition的注册和加载有什么区别?
注册是将已创建的BeanDefinition添加到容器中,而加载是从外部配置文件中读取Bean的元信息并注册到容器中。
8. 如何使用BeanDefinition来实现依赖注入?
通过设置BeanDefinition中的属性,如构造函数参数、属性值、引用其他Bean的方式,可以实现依赖注入。
9. BeanDefinition是否可以动态生成?
可以在运行时动态生成并注册到容器中,这在某些复杂的情况下非常有用,例如基于条件的Bean注册。