Spring-ApplicationContext

简介: Spring-ApplicationContext

一、ApplicationContext


  ApplicationContext到底是什么?字面含义是应用的上下文。这块我们需要看看ApplicationContext的具体的结构。

image.png

  通过ApplicationContext实现的相关接口来分析,ApplicationContext接口在具备BeanFactory的功能的基础上还扩展了 应用事件发布,资源加载,环境参数国际化的能力。然后我们来看看ApplicationContext接口的实现类的情况。

image.png

  在ApplicationContext的实现类中有两个比较重要的分支 AbstractRefreshableApplicationContextGenericApplicationContext.

image.png



二、BeanFactory


  上面分析了 ApplicationContext接口的结构。然后我们来看看 BeanFactory在ApplicationContext中具体的实现是怎么样的

image.png

image.png


可以看到具体的实现是 DefaultListableBeanFactory .然后我们来看看他的体系结构

image.png


BeanFactory的继承体系

image.png




三、BeanDefinition


  然后我们来了解下ApplicationContext是如何来加载Bean定义的。具体代码我们需要分为XML配置文件和基于注解的两种方式来看。



1.基于XML方式


  我们先定义对应的application.xml文件


<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:context="http://www.springframework.org/schema/context"
    xmlns:aop="http://www.springframework.org/schema/aop"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context.xsd
        http://www.springframework.org/schema/aop
        http://www.springframework.org/schema/aop/spring-aop.xsd">
  <bean id="beanE" class="com.study.spring.sample.config.BeanE" />
  <bean id="beanF" class="com.study.spring.sample.config.BeanF" ></bean>
  <context:annotation-config/>
  <context:component-scan base-package="com.study.spring.sample.config" ></context:component-scan>
</beans>
复制代码


然后我们的测试类代码


public class XMLConfigMain {
  public static void main(String[] args) {
    ApplicationContext context = new GenericXmlApplicationContext(
        "classpath:com/study/spring/sample/config/application.xml");
    BeanF bf = context.getBean(BeanF.class);
    bf.do1();
  }
}
复制代码


处理的过程  解析XML --> BeanDefinition --> BeanDefinitionRegistry --> BeanFactory


image.png

2.基于注解方式


  然后来看看基于注解方式的使用的情况。首先是我们的配置类


@Configuration
@ComponentScan("com.study.spring.sample.config")
public class JavaBasedMain {
  @Bean
  public BeanH getBeanH() {
    return new BeanH();
  }
  public static void main(String[] args) {
    ApplicationContext context = new AnnotationConfigApplicationContext(JavaBasedMain.class);
    BeanH bh = context.getBean(BeanH.class);
    bh.doH();
  }
}
复制代码


然后是我们的测试类


public class AnnotationMain {
  public static void main(String[] args) {
    ApplicationContext context = new AnnotationConfigApplicationContext("com.study.spring.sample.config");
    BeanG bg = context.getBean(BeanG.class);
    bg.dog();
  }
}
复制代码


注解使用有两种方法:


  1. 配置扫描路径


  1. 配置@Configuration的注解类



2.1 this构造方法


  在this的构造方法中会完成相关的配置处理。


public AnnotationConfigApplicationContext() {
    this.reader = new AnnotatedBeanDefinitionReader(this);
    this.scanner = new ClassPathBeanDefinitionScanner(this);
  }
复制代码


首先是AnnotatedBeanDefinitionReader(this)方法。会完成核心的

ConfigurationClassPostProcessor的注入。ConfigurationClassPostProcessor 会完成@Configuration相关的注解的解析

image.png


this.scanner其实就是创建了一个对应的扫描器

image.png



2.2 扫描实现


  扫描就需要进入到scan方法中。

image.png

image.png

image.png

完成相关的注册

image.png


2.3 @Configuration


  @Configuration的解析其实是在refresh方法中来实现的。


image.png


3.小结


  通过上面的分析其实我们已经对Bean定义的扫描,解析和注册过程有了一定的了解。归纳为:


  1. reader解析XML,完成xml方法配置的bean定义


  1. scanner扫描指定包下的类,找出带有@Component注解的类,注册成Bean定义


  1. 通过ConfigurationClassPostProcessor对带有@Configuration注解的类进行处理,解析它上面的注解,以及类中带有@Bean 注解,加入这些的Bean的定义。



4.BeanDefinition


  ;然后我们来看看BeanDefinition的继承结构


image.png

  继承属性访问器和元数据接口,增加了Bean定义操作,实现了数据和操作解耦。属性访问器和元数据接口接着往下看。


4.1 BeanMetadataElement


  BeanMetadataElement提供了获取数据源的方式,也就是可以指导Bean是来自哪个类。


public interface BeanMetadataElement {
  /**
   * Return the configuration source {@code Object} for this metadata element
   * (may be {@code null}).
   */
  @Nullable
  default Object getSource() {
    return null;
  }
}
复制代码


4.2 BeanMetadataAttribute元数据属性


  实现了元数据接口,增加了属性的名字和值。。


public class BeanMetadataAttribute implements BeanMetadataElement {
  private final String name;
  @Nullable
  private final Object value;
  @Nullable
  private Object source;
}
复制代码


4.3 AttributeAccessor属性访问器


  AttributeAccessor用来给Bean定义了增删改查属性的功能


public interface AttributeAccessor {
  /**
   * Set the attribute defined by {@code name} to the supplied {@code value}.
   * If {@code value} is {@code null}, the attribute is {@link #removeAttribute removed}.
   * <p>In general, users should take care to prevent overlaps with other
   * metadata attributes by using fully-qualified names, perhaps using
   * class or package names as prefix.
   * @param name the unique attribute key
   * @param value the attribute value to be attached
   */
  void setAttribute(String name, @Nullable Object value);
  /**
   * Get the value of the attribute identified by {@code name}.
   * Return {@code null} if the attribute doesn't exist.
   * @param name the unique attribute key
   * @return the current value of the attribute, if any
   */
  @Nullable
  Object getAttribute(String name);
  /**
   * Remove the attribute identified by {@code name} and return its value.
   * Return {@code null} if no attribute under {@code name} is found.
   * @param name the unique attribute key
   * @return the last value of the attribute, if any
   */
  @Nullable
  Object removeAttribute(String name);
  /**
   * Return {@code true} if the attribute identified by {@code name} exists.
   * Otherwise return {@code false}.
   * @param name the unique attribute key
   */
  boolean hasAttribute(String name);
  /**
   * Return the names of all attributes.
   */
  String[] attributeNames();
}
复制代码


4.4 AttributeAccessorSupport属性访问抽象实现类


  内部定义了1个map来存放属性。


public abstract class AttributeAccessorSupport implements AttributeAccessor, Serializable {
  /** Map with String keys and Object values. */
  private final Map<String, Object> attributes = new LinkedHashMap<>();
  @Override
  public void setAttribute(String name, @Nullable Object value) {
    Assert.notNull(name, "Name must not be null");
    if (value != null) {
      this.attributes.put(name, value);
    }
    else {
      removeAttribute(name);
    }
  }
    //  ......
}
复制代码


4.5 BeanMetadataAttributeAccessor元数据属性访问器


  继承AttributeAccessorSupport具备属性访问功能,实现BeanMetadataElement具备获取元数据功能。 **AbstractBeanDefinition就继承于它,使得同时具有属性访问和元数据访问的功能 **。

image.png


结合AbstractBeanDefinition.来看看他们的类图结构

image.png

5. BeanDefinition继承体系


5.1 AnnotatedBeanDefinition


  增加了2个方法,获取bean所在类的注解元数据和工厂方法元数据,这些数据在进行解析处理的时候需要用到。


public interface AnnotatedBeanDefinition extends BeanDefinition {
  /**
   * Obtain the annotation metadata (as well as basic class metadata)
   * for this bean definition's bean class.
   * @return the annotation metadata object (never {@code null})
   */
  AnnotationMetadata getMetadata();
  /**
   * Obtain metadata for this bean definition's factory method, if any.
   * @return the factory method metadata, or {@code null} if none
   * @since 4.1.1
   */
  @Nullable
  MethodMetadata getFactoryMethodMetadata();
}
复制代码


  该注解有三个具体的实现。ScannedGenericBeanDefinition、

AnnotatedGenericBeanDefinition、ConfigurationClassBeanDefinition。


image.png

5.2 AbstractBeanDefinition模板类


  AbstractBeanDefinition我们可以称之为BeanDefinition的模板类。结构我们上面其实有梳理


image.png

  通过上面我们可以看到AbstractBeanDefinition 具备了 Bean元数据的获取和属性相关的操作。同时AbstractBeanDefinition的继承结构

image.png

5.3 RootBeanDefinition根bean定义


  它主要用在spring内部的bean定义、把不同类型的bean定义合并成RootBeanDefinition(getMergedLocalBeanDefinition方法)。没有实现BeanDefinition接口的设置获取父bean定义方法,不支持设置父子beanDefinition。



5.4 ConfigurationClassBeanDefinition


  用作ConfigurationClassPostProcessor解析过程中封装配置类的bean定义。


5.5 GenericBeanDefinition


  GenericBeanDefinition通用Bean的定义。


5.6 ScannedGenericBeanDefinition


  @ComponentScan扫描的bean定义使用。



5.7 AnnotatedGenericBeanDefinition



相关文章
|
SQL Oracle 关系型数据库
【MySQL异常】1093 - You can‘t specify target table ‘daily_job‘ for update in FROM clause
【MySQL异常】1093 - You can‘t specify target table ‘daily_job‘ for update in FROM clause
525 0
|
存储 关系型数据库 MySQL
MVCC多版本并发控制
MVCC多版本并发控制 1、MVCC MVCC,全称Multi-Version Concurrency Control,即多版本并发控制。MVCC是一种并发控制的方法,一般在数据库管理系统中,实现对数据库的并发访问,在编程语言中实现事务内存。
736 0
|
算法 机器学习/深度学习 数据安全/隐私保护
murmur3哈希算法
murmur3哈希算法 murmur3非加密哈希算法 murmur3非加密哈希算法导图 据算法作者Austin Appleby描述,有c1, c2, n 三个常量用大量测试数据调测出来的,可以对数值进行微调。
14723 0
|
6月前
|
设计模式 SQL 安全
并发设计模式实战系列(13):双重检查锁定(Double-Checked Locking)
🌟 大家好,我是摘星!🌟今天为大家带来的是并发设计模式实战系列,第十三章,废话不多说直接开始~
374 0
|
消息中间件 JSON Java
Spring Boot、Spring Cloud与Spring Cloud Alibaba版本对应关系
Spring Boot、Spring Cloud与Spring Cloud Alibaba版本对应关系
27983 0
|
5月前
|
NoSQL 安全 Java
Redisson框架使用:支持高并发的RBucket功能剖析
整体来看,无论你是在开发新的分布式应用,还是在维护一个现有的大型系统,Redisson 框架和 RBucket 功能都能为你提供非常大的帮助。正如扳手能让你轻松地拧紧螺丝,Redisson 和 RBucket 也能让你轻松处理并发的问题。一起来享受编程的乐趣吧!
319 10
|
10月前
|
机器学习/深度学习 人工智能 算法
机器学习算法的优化与改进:提升模型性能的策略与方法
机器学习算法的优化与改进:提升模型性能的策略与方法
1865 13
机器学习算法的优化与改进:提升模型性能的策略与方法
|
运维 监控 持续交付
"揭秘Puppet:自动化运维的超级英雄,一键驾驭复杂IT环境,让运维繁琐瞬间灰飞烟灭,引领未来运维新纪元!"
【8月更文挑战第9天】Puppet作为自动化运维的杰出代表,凭借其强大的配置管理和高度可定制性,助力IT运维实现自动化与智能化转型。通过定义资源模型与使用声明式语言描述系统状态,Puppet能自动调整系统至期望状态,实现标准化运维流程。其工作流程包括定义-应用-报告三步,支持从服务器配置到复杂网络、数据库管理等多种场景。示例代码展示了如何自动化部署Apache服务器,体现了Puppet在实际操作中的高效与便捷。随着技术演进与社区壮大,Puppet将持续推动运维领域的创新发展。
315 6
|
算法 vr&ar
状态空间模型:卡尔曼滤波器KFAS建模时间序列
状态空间模型:卡尔曼滤波器KFAS建模时间序列
|
消息中间件 Java 测试技术
技术分享:探讨@Transactional与@Async的共舞——能否同时使用及最佳实践
【8月更文挑战第13天】在Java的Spring框架中,@Transactional和@Async是两个非常强大的注解,它们分别用于控制事务的边界和优化应用程序的性能通过异步执行。然而,当这两个注解碰撞在一起时,是否能够和谐共存,成为了很多开发者在设计和构建高性能、高可靠性的应用程序时面临的一个关键问题。本文将深入探讨@Transactional与@Async的联合使用场景、潜在问题以及最佳实践。
736 0