【死磕 Spring】----- IOC 之解析 bean 标签:BeanDefinition

本文涉及的产品
云解析 DNS,旗舰版 1个月
公共DNS(含HTTPDNS解析),每月1000万次HTTP解析
全局流量管理 GTM,标准版 1个月
简介:
前面历经千辛万苦终于到达解析 bean 标签步骤来了,解析 bean 标签的过程其实就是构造一个 BeanDefinition 对象的过程, <bean> 元素标签拥有的配置属性,BeanDefinition 均提供了相应的属性,与之一一对应。所以我们有必要对 BeanDefinition 有一个整体的认识。
BeanDefinition

BeanDefinition 是一个接口,它描述了一个 Bean 实例,包括属性值、构造方法值和继承自它的类的更多信息。它继承 AttributeAccessor 和 BeanMetadataElement 接口。两个接口定义如下:

  • AttributeAccessor :定义了与其它对象的(元数据)进行连接和访问的约定,即对属性的修改,包括获取、设置、删除。

  • BeanMetadataElement:Bean 元对象持有的配置元素可以通过 getSource() 方法来获取。

BeanDefinition 整个结构如下图:

c2ea6d274124612dfdcdaffced6adf17714a8a32

我们常用的三个实现类有:ChildBeanDefinition、GenericBeanDefinition、RootBeanDefinition,三者都继承 AbstractBeanDefinition。如果配置文件中定义了父 <bean> 和 子 <bean> ,则父 <bean> 用 RootBeanDefinition表示,子 <bean> 用 ChildBeanDefinition 表示,而没有父 <bean> 的就使用RootBeanDefinition 表示。GenericBeanDefinition 为一站式服务类。AbstractBeanDefinition对三个子类共同的类信息进行抽象。

解析 Bean 标签

BeanDefinitionParserDelegate.parseBeanDefinitionElement() 中完成 Bean 的解析,返回的是一个已经完成对 <bean> 标签解析的 BeanDefinition 实例。在该方法内部,首先调用 createBeanDefinition() 方法创建一个用于承载属性的 GenericBeanDefinition 实例,如下:

 
  1. protected AbstractBeanDefinition createBeanDefinition(@Nullable String className, @Nullable String parentName)

  2. throws ClassNotFoundException {

  3. return BeanDefinitionReaderUtils.createBeanDefinition(

  4. parentName, className, this.readerContext.getBeanClassLoader());

  5. }

委托 BeanDefinitionReaderUtils 创建,如下:

 
  1. public static AbstractBeanDefinition createBeanDefinition(

  2. @Nullable String parentName, @Nullable String className, @Nullable ClassLoader classLoader) throws ClassNotFoundException {


  3. GenericBeanDefinition bd = new GenericBeanDefinition();

  4. bd.setParentName(parentName);

  5. if (className != null) {

  6. if (classLoader != null) {

  7. bd.setBeanClass(ClassUtils.forName(className, classLoader));

  8. }

  9. else {

  10. bd.setBeanClassName(className);

  11. }

  12. }

  13. return bd;

  14. }

该方法主要是设置 parentName 、className、classLoader。

创建完 GenericBeanDefinition 实例后,再调用 parseBeanDefinitionAttributes(),该方法将创建好的 GenericBeanDefinition 实例当做参数,对 Bean 标签的所有属性进行解析,如下:

 
  1. public AbstractBeanDefinition parseBeanDefinitionAttributes(Element ele, String beanName,

  2. @Nullable BeanDefinition containingBean, AbstractBeanDefinition bd) {

  3. // 解析 scope 标签

  4. if (ele.hasAttribute(SINGLETON_ATTRIBUTE)) {

  5. error("Old 1.x 'singleton' attribute in use - upgrade to 'scope' declaration", ele);

  6. }

  7. else if (ele.hasAttribute(SCOPE_ATTRIBUTE)) {

  8. bd.setScope(ele.getAttribute(SCOPE_ATTRIBUTE));

  9. }

  10. else if (containingBean != null) {

  11. // Take default from containing bean in case of an inner bean definition.

  12. bd.setScope(containingBean.getScope());

  13. }


  14. // 解析 abstract 标签

  15. if (ele.hasAttribute(ABSTRACT_ATTRIBUTE)) {

  16. bd.setAbstract(TRUE_VALUE.equals(ele.getAttribute(ABSTRACT_ATTRIBUTE)));

  17. }


  18. // 解析 lazy-init 标签

  19. String lazyInit = ele.getAttribute(LAZY_INIT_ATTRIBUTE);

  20. if (DEFAULT_VALUE.equals(lazyInit)) {

  21. lazyInit = this.defaults.getLazyInit();

  22. }

  23. bd.setLazyInit(TRUE_VALUE.equals(lazyInit));


  24. // 解析 autowire 标签

  25. String autowire = ele.getAttribute(AUTOWIRE_ATTRIBUTE);

  26. bd.setAutowireMode(getAutowireMode(autowire));


  27. // 解析 depends-on 标签

  28. if (ele.hasAttribute(DEPENDS_ON_ATTRIBUTE)) {

  29. String dependsOn = ele.getAttribute(DEPENDS_ON_ATTRIBUTE);

  30. bd.setDependsOn(StringUtils.tokenizeToStringArray(dependsOn, MULTI_VALUE_ATTRIBUTE_DELIMITERS));

  31. }


  32. // 解析 autowire-candidate 标签

  33. String autowireCandidate = ele.getAttribute(AUTOWIRE_CANDIDATE_ATTRIBUTE);

  34. if ("".equals(autowireCandidate) || DEFAULT_VALUE.equals(autowireCandidate)) {

  35. String candidatePattern = this.defaults.getAutowireCandidates();

  36. if (candidatePattern != null) {

  37. String[] patterns = StringUtils.commaDelimitedListToStringArray(candidatePattern);

  38. bd.setAutowireCandidate(PatternMatchUtils.simpleMatch(patterns, beanName));

  39. }

  40. }

  41. else {

  42. bd.setAutowireCandidate(TRUE_VALUE.equals(autowireCandidate));

  43. }


  44. // 解析 primay 标签

  45. if (ele.hasAttribute(PRIMARY_ATTRIBUTE)) {

  46. bd.setPrimary(TRUE_VALUE.equals(ele.getAttribute(PRIMARY_ATTRIBUTE)));

  47. }


  48. // 解析 init-method 标签

  49. if (ele.hasAttribute(INIT_METHOD_ATTRIBUTE)) {

  50. String initMethodName = ele.getAttribute(INIT_METHOD_ATTRIBUTE);

  51. bd.setInitMethodName(initMethodName);

  52. }

  53. else if (this.defaults.getInitMethod() != null) {

  54. bd.setInitMethodName(this.defaults.getInitMethod());

  55. bd.setEnforceInitMethod(false);

  56. }


  57. // 解析 destroy-mothod 标签

  58. if (ele.hasAttribute(DESTROY_METHOD_ATTRIBUTE)) {

  59. String destroyMethodName = ele.getAttribute(DESTROY_METHOD_ATTRIBUTE);

  60. bd.setDestroyMethodName(destroyMethodName);

  61. }

  62. else if (this.defaults.getDestroyMethod() != null) {

  63. bd.setDestroyMethodName(this.defaults.getDestroyMethod());

  64. bd.setEnforceDestroyMethod(false);

  65. }


  66. // 解析 factory-method 标签

  67. if (ele.hasAttribute(FACTORY_METHOD_ATTRIBUTE)) {

  68. bd.setFactoryMethodName(ele.getAttribute(FACTORY_METHOD_ATTRIBUTE));

  69. }

  70. if (ele.hasAttribute(FACTORY_BEAN_ATTRIBUTE)) {

  71. bd.setFactoryBeanName(ele.getAttribute(FACTORY_BEAN_ATTRIBUTE));

  72. }


  73. return bd;

  74. }

从上面代码我们可以清晰地看到对 Bean 标签属性的解析,这些属性我们在工作中都或多或少用到过。

完成 Bean 标签基本属性解析后,会依次调用 parseMetaElements()parseLookupOverrideSubElements()parseReplacedMethodSubElements()对子元素 meta、lookup-method、replace-method 完成解析。下篇博文将会对这三个子元素进行详细说明。


原文发布时间为:2018-09-19
本文作者: Java技术驿站
本文来自云栖社区合作伙伴“ ”,了解相关信息可以关注“ Java技术驿站”。

相关文章
|
1月前
|
传感器 监控 安全
智慧工地云平台的技术架构解析:微服务+Spring Cloud如何支撑海量数据?
慧工地解决方案依托AI、物联网和BIM技术,实现对施工现场的全方位、立体化管理。通过规范施工、减少安全隐患、节省人力、降低运营成本,提升工地管理的安全性、效率和精益度。该方案适用于大型建筑、基础设施、房地产开发等场景,具备微服务架构、大数据与AI分析、物联网设备联网、多端协同等创新点,推动建筑行业向数字化、智能化转型。未来将融合5G、区块链等技术,助力智慧城市建设。
|
1月前
|
XML Java 测试技术
Spring IOC—基于注解配置和管理Bean 万字详解(通俗易懂)
Spring 第三节 IOC——基于注解配置和管理Bean 万字详解!
129 26
|
2月前
|
XML Java 开发者
Spring底层架构核心概念解析
理解 Spring 框架的核心概念对于开发和维护 Spring 应用程序至关重要。IOC 和 AOP 是其两个关键特性,通过依赖注入和面向切面编程实现了高效的模块化和松耦合设计。Spring 容器管理着 Beans 的生命周期和配置,而核心模块为各种应用场景提供了丰富的功能支持。通过全面掌握这些核心概念,开发者可以更加高效地利用 Spring 框架开发企业级应用。
89 18
|
3月前
|
存储 Java 应用服务中间件
【Spring】IoC和DI,控制反转,Bean对象的获取方式
IoC,DI,控制反转容器,Bean的基本常识,类注解@Controller,获取Bean对象的常用三种方式
|
3月前
|
设计模式 XML Java
【23种设计模式·全精解析 | 自定义Spring框架篇】Spring核心源码分析+自定义Spring的IOC功能,依赖注入功能
本文详细介绍了Spring框架的核心功能,并通过手写自定义Spring框架的方式,深入理解了Spring的IOC(控制反转)和DI(依赖注入)功能,并且学会实际运用设计模式到真实开发中。
【23种设计模式·全精解析 | 自定义Spring框架篇】Spring核心源码分析+自定义Spring的IOC功能,依赖注入功能
|
4月前
|
前端开发 Java 开发者
Spring MVC中的请求映射:@RequestMapping注解深度解析
在Spring MVC框架中,`@RequestMapping`注解是实现请求映射的关键,它将HTTP请求映射到相应的处理器方法上。本文将深入探讨`@RequestMapping`注解的工作原理、使用方法以及最佳实践,为开发者提供一份详尽的技术干货。
287 2
|
4月前
|
前端开发 Java Spring
探索Spring MVC:@Controller注解的全面解析
在Spring MVC框架中,`@Controller`注解是构建Web应用程序的基石之一。它不仅简化了控制器的定义,还提供了一种优雅的方式来处理HTTP请求。本文将全面解析`@Controller`注解,包括其定义、用法、以及在Spring MVC中的作用。
97 2
|
4月前
|
前端开发 Java 开发者
Spring MVC中的控制器:@Controller注解全解析
在Spring MVC框架中,`@Controller`注解是构建Web应用程序控制层的核心。它不仅简化了控制器的定义,还提供了灵活的请求映射和处理机制。本文将深入探讨`@Controller`注解的用法、特点以及在实际开发中的应用。
191 0
|
4月前
|
前端开发 Java Maven
深入解析:如何用 Spring Boot 实现分页和排序
深入解析:如何用 Spring Boot 实现分页和排序
201 2
|
4月前
|
Java 开发者 Spring
Spring AOP深度解析:探秘动态代理与增强逻辑
Spring框架中的AOP(Aspect-Oriented Programming,面向切面编程)功能为开发者提供了一种强大的工具,用以将横切关注点(如日志、事务管理等)与业务逻辑分离。本文将深入探讨Spring AOP的底层原理,包括动态代理机制和增强逻辑的实现。
86 4

热门文章

最新文章

推荐镜像

更多