IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 系统运维 -> Spring启动之初始化容器 -> 正文阅读

[系统运维]Spring启动之初始化容器

1、前言

  • Spring会将所有交由Spring管理的类,扫描其class文件,将其解析成BeanDefinition,在BeanDefinition中会描述类的信息,例如:这个类是否是单例的,Bean的类型,是否是懒加载,依赖哪些类,自动装配的模型。Spring创建对象时,就是根据BeanDefinition中的信息来创建Bean
  • Spring容器在本文可以简单理解为DefaultListableBeanFactory,它是BeanFactory的实现类,这个类有几个非常重要的属性:beanDefinitionMap是一个map,用来存放bean所对应的BeanDefinition;beanDefinitionNames是一个List集合,用来存放所有bean的name;singletonObjects是一个Map,用来存放所有创建好的单例Bean
  • Spring中有很多后置处理器,但最终可以分为两种,一种是BeanFactoryPostProcessor,一种是BeanPostProcessor。前者的用途是用来干预BeanFactory的创建过程,后者是用来干预Bean的创建过程。后置处理器的作用十分重要,bean的创建以及AOP的实现全部依赖后置处理器

2、入口

2.1、主方法

public static void main(String[] args) {
    AnnotationConfigApplicationContext acac = new AnnotationConfigApplicationContext(ComponentScanTest.class);
    String[] beanDefinitionNames = acac.getBeanDefinitionNames();
    Arrays.asList(beanDefinitionNames).stream().forEach(System.out::println);
}

2.2、配置类

  • ComponentScanTest 类是一个配置类,类上加了两个注解,加 @Configuration 表明``ComponentScanTest是一个配置类,加@ComponentScan是为了告诉Spring` 要扫描哪些包
// 不加该注解也可扫描到
@Configuration
@ComponentScan("org.springframework.test")
public class ComponentScanTest {
}

3、AnnotationConfigApplicationContext构造方法

public AnnotationConfigApplicationContext(Class<?>... annotatedClasses) {
	// 会初始化一个BeanFactory,为默认的DefaultListableBeanFactory
	// 会初始化一个beanDefinition的读取器,同时向容器中注册了7个spring的后置处理器(包括BeanPostProcessor和BeanFactoryPostProcessor)
	// 会初始化一个扫描器,后面似乎并没有用到这个扫描器,在refresh()中使用的是重新new的一个扫描器。
	this();
	register(annotatedClasses);
	refresh();
}

4、AnnotationConfigApplicationContext之构造方法加载

  • this()会调用AnnotationConfigApplicationContext无参构造方法,而在Java的继承中,会先调用父类的构造方法
  • 构造方法调用顺序为:DefaultResourceLoader -> AbstractApplicationContext -> GenericApplicationContext -> AnnotationConfigApplicationContext

4.1、初始化DefaultResourceLoader

  • 初始化了一个类加载器
public DefaultResourceLoader() {
   // 初始化classLoader成员变量为:系统类加载器AppClassLoader
   this.classLoader = ClassUtils.getDefaultClassLoader();
}

4.2、初始化AbstractApplicationContext

  • 初始化了一个资源模式解析器、资源加载器
public AbstractApplicationContext() {
    // 初始化资源模式解析器为:PathMatchingResourcePatternResolver
    this.resourcePatternResolver = getResourcePatternResolver();
}

4.2.1、获取资源模式解析器

protected ResourcePatternResolver getResourcePatternResolver() {
    // this为:AnnotationConfigApplicationContext
    return new PathMatchingResourcePatternResolver(this);
}

4.2.2、初始化资源模式解析器

public PathMatchingResourcePatternResolver(ResourceLoader resourceLoader) {
    Assert.notNull(resourceLoader, "ResourceLoader must not be null");
    // 初始化资源加载器为:AnnotationConfigApplicationContext
    this.resourceLoader = resourceLoader;
}

4.3、初始化GenericApplicationContext

  • 创建了一个容器:DefaultListableBeanFactory
public GenericApplicationContext() {
    // 初始化容器为:DefaultListableBeanFactory
    this.beanFactory = new DefaultListableBeanFactory();
}

4.3.1、初始化AbstractAutowireCapableBeanFactory

  • DefaultListableBeanFactory的父类AbstractAutowireCapableBeanFactory会先于其构造执行
// 初始化AbstractAutowireCapableBeanFactory
public AbstractAutowireCapableBeanFactory() {
   super();
    // 依赖项检查和@autowire中要忽略的依赖项接口,作为类对象。默认情况下,仅忽略BeanFactory接口
   ignoreDependencyInterface(BeanNameAware.class);
   ignoreDependencyInterface(BeanFactoryAware.class);
   ignoreDependencyInterface(BeanClassLoaderAware.class);
}

4.4、初始化AnnotationConfigApplicationContext

public AnnotationConfigApplicationContext() {
    // 带注释的Bean定义读取器
    this.reader = new AnnotatedBeanDefinitionReader(this);
    // 类路径Bean定义扫描器
    this.scanner = new ClassPathBeanDefinitionScanner(this);
}

5、this方法之AnnotatedBeanDefinitionReader读取器

public AnnotatedBeanDefinitionReader(BeanDefinitionRegistry registry) {
   this(registry, getOrCreateEnvironment(registry));
}

5.1、创建环境

// 入参registry:AnnotationConfigApplicationContext实现了
private static Environment getOrCreateEnvironment(BeanDefinitionRegistry registry) {
    Assert.notNull(registry, "BeanDefinitionRegistry must not be null");
    // AnnotationConfigApplicationContext实现了EnvironmentCapable接口
    if (registry instanceof EnvironmentCapable) {
        return ((EnvironmentCapable) registry).getEnvironment();
    }
    return new StandardEnvironment();
}
@Override
public ConfigurableEnvironment getEnvironment() {
    // 初始化容器时环境,org.springframework.context.support.AbstractApplicationContext#AbstractApplicationContext的成员变量ConfigurableEnvironment environment = null
    if (this.environment == null) {
        this.environment = createEnvironment();
    }
    return this.environment;
}
protected ConfigurableEnvironment createEnvironment() {
	// 创建一个标准环境,其父类AbstractEnvironment初始化了MutablePropertySources可变属性源
    return new StandardEnvironment();
}

5.2、初始化读取器

public AnnotatedBeanDefinitionReader(BeanDefinitionRegistry registry, Environment environment) {
    Assert.notNull(registry, "BeanDefinitionRegistry must not be null");
    Assert.notNull(environment, "Environment must not be null");
    // 初始化BeanDefinitionRegistry
    this.registry = registry;
    // 初始化confition鉴别器,用于@Confitional注解解析
    this.conditionEvaluator = new ConditionEvaluator(registry, environment, null);
    // 注册7个内置后置处理器
    AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry);
}

5.2.1、初始化Condition鉴别器

// org.springframework.context.annotation.ConditionEvaluator
public ConditionEvaluator(@Nullable BeanDefinitionRegistry registry,
                          @Nullable Environment environment, @Nullable ResourceLoader resourceLoader) {
	// 初始化内部类ConditionContextImpl
    this.context = new ConditionContextImpl(registry, environment, resourceLoader);
}
5.2.1.1、初始化ConditionEvaluator内部类ConditionContextImpl
public ConditionContextImpl(@Nullable BeanDefinitionRegistry registry,
                            @Nullable Environment environment, @Nullable ResourceLoader resourceLoader) {
	// AnnotationConfigApplicationContext
    this.registry = registry;
    // 推断容器:DefaultListableBeanFactory
    this.beanFactory = deduceBeanFactory(registry);
    // 推断环境:StandardEnvironment
    this.environment = (environment != null ? environment : deduceEnvironment(registry));
    // 推断资源加载器:AnnotationConfigApplicationContext
    this.resourceLoader = (resourceLoader != null ? resourceLoader : deduceResourceLoader(registry));
    // 推断类加载器:统类加载器AppClassLoader
    this.classLoader = deduceClassLoader(resourceLoader, this.beanFactory);
}

5.2.2、注册7大内置后置处理器

  • 此时BeanDefinition中只设置了beanName和beanClass属性值
public static Set<BeanDefinitionHolder> registerAnnotationConfigProcessors(
    BeanDefinitionRegistry registry, @Nullable Object source) {
    // 1.将AnnotationConfigApplicationContext转换为DefaultListableBeanFactory
    DefaultListableBeanFactory beanFactory = unwrapDefaultListableBeanFactory(registry);

    if (beanFactory != null) {
        // 2.容器初始化时DependencyComparator为null,此时会进入判断
        if (!(beanFactory.getDependencyComparator() instanceof AnnotationAwareOrderComparator)) {
            // 设置默认bean排序比较器:AnnotationAwareOrderComparator继承OrderComparator
        beanFactory.setDependencyComparator(AnnotationAwareOrderComparator.INSTANCE);
        }
        // 3.容器初始化时候选自动装配解析器AutowireCandidateResolver = SimpleAutowireCandidateResolver,而没有实现ContextAnnotationAutowireCandidateResolver,则会进入
        if (!(beanFactory.getAutowireCandidateResolver() instanceof ContextAnnotationAutowireCandidateResolver)) {
            // 设置候选自动装配解析器:AutowireCandidateResolver = ContextAnnotationAutowireCandidateResolver
            beanFactory.setAutowireCandidateResolver(new ContextAnnotationAutowireCandidateResolver());
        }
    }

    Set<BeanDefinitionHolder> beanDefs = new LinkedHashSet<>(8);
    // 4. 注册后置处理器ConfigurationClassPostProcessor 实现了 BeanDefinitionRegistryPostProcessor
    if (!registry.containsBeanDefinition(CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME)) {
        // 用来解析加了@Configuration的配置类,还会解析@ComponentScan、@ComponentScans注解扫描的包,以及解析@Component、@Import、@ImportResource注解,以及@Bean注解的方法
        RootBeanDefinition def = new RootBeanDefinition(ConfigurationClassPostProcessor.class);
        def.setSource(source);
        beanDefs.add(registerPostProcessor(registry, def, CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME));
    }
    // 5.用来解析@Autowired和@Value、@Inject注解
    if (!registry.containsBeanDefinition(AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME)) {
        RootBeanDefinition def = new RootBeanDefinition(AutowiredAnnotationBeanPostProcessor.class);
        def.setSource(source);
        beanDefs.add(registerPostProcessor(registry, def, AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME));
    }
    // 6.注册RequiredAnnotationBeanPostProcessor,
    if (!registry.containsBeanDefinition(REQUIRED_ANNOTATION_PROCESSOR_BEAN_NAME)) {
        RootBeanDefinition def = new RootBeanDefinition(RequiredAnnotationBeanPostProcessor.class);
        def.setSource(source);
        beanDefs.add(registerPostProcessor(registry, def, REQUIRED_ANNOTATION_PROCESSOR_BEAN_NAME));
    }

    // 7.注册CommonAnnotationBeanPostProcessor,用来处理如@PostConstruct、@PreDestroy和@Resource等符合JSR-250规范的注解
    if (jsr250Present && !registry.containsBeanDefinition(COMMON_ANNOTATION_PROCESSOR_BEAN_NAME)) {
        RootBeanDefinition def = new RootBeanDefinition(CommonAnnotationBeanPostProcessor.class);
        def.setSource(source);
        beanDefs.add(registerPostProcessor(registry, def, COMMON_ANNOTATION_PROCESSOR_BEAN_NAME));
    }

    // 8. 注册PersistenceAnnotationBeanPostProcessor,来用支持JPA
    if (jpaPresent && !registry.containsBeanDefinition(PERSISTENCE_ANNOTATION_PROCESSOR_BEAN_NAME)) {
        RootBeanDefinition def = new RootBeanDefinition();
        try {
            def.setBeanClass(ClassUtils.forName(PERSISTENCE_ANNOTATION_PROCESSOR_CLASS_NAME,
                                                AnnotationConfigUtils.class.getClassLoader()));
        } catch (ClassNotFoundException ex) {
            throw new IllegalStateException(
                "Cannot load optional framework class: " + PERSISTENCE_ANNOTATION_PROCESSOR_CLASS_NAME, ex);
        }
        def.setSource(source);
        beanDefs.add(registerPostProcessor(registry, def, PERSISTENCE_ANNOTATION_PROCESSOR_BEAN_NAME));
    }
    // 9.用来处理@EventListener事件监听注解,用来处理方法上加了@EventListener的注解
    if (!registry.containsBeanDefinition(EVENT_LISTENER_PROCESSOR_BEAN_NAME)) {
        RootBeanDefinition def = new RootBeanDefinition(EventListenerMethodProcessor.class);
        def.setSource(source);
        beanDefs.add(registerPostProcessor(registry, def, EVENT_LISTENER_PROCESSOR_BEAN_NAME));
    }
    // 10.注册事件监听器工厂
    if (!registry.containsBeanDefinition(EVENT_LISTENER_FACTORY_BEAN_NAME)) {
        RootBeanDefinition def = new RootBeanDefinition(DefaultEventListenerFactory.class);
        def.setSource(source);
        beanDefs.add(registerPostProcessor(registry, def, EVENT_LISTENER_FACTORY_BEAN_NAME));
    }

    return beanDefs;
}

6、this方法之ClassPathBeanDefinitionScanner扫描器

6.1、ClassPathBeanDefinitionScanner构造方法

// 最终会走到该构造方法处,
public ClassPathBeanDefinitionScanner(BeanDefinitionRegistry registry, boolean useDefaultFilters,
                                      Environment environment, @Nullable ResourceLoader resourceLoader) {

    Assert.notNull(registry, "BeanDefinitionRegistry must not be null");
    this.registry = registry;

    // 给父类ClassPathScanningCandidateComponentProvider的成员属性includeFilters赋值(@Component、@javax.annotation.ManagedBean、@javax.inject.Named)
    // useDefaultFilters默认为true
    if (useDefaultFilters) {
        registerDefaultFilters();
    }
    // 设置系统运行环境(标准环境StandardEnvironment)
    setEnvironment(environment);
    // 设置资源加载器(同registry都是AnnotationConfigApplicationContext)
    setResourceLoader(resourceLoader);
}

6.2、registerDefaultFilters

  • 给父类ClassPathScanningCandidateComponentProvider的includeFilters属性赋值
// 注册默认过滤器
protected void registerDefaultFilters() {
    this.includeFilters.add(new AnnotationTypeFilter(Component.class));
    ClassLoader cl = ClassPathScanningCandidateComponentProvider.class.getClassLoader();
    try {
        this.includeFilters.add(new AnnotationTypeFilter(
            ((Class<? extends Annotation>) ClassUtils.forName("javax.annotation.ManagedBean", cl)), false));
        logger.debug("JSR-250 'javax.annotation.ManagedBean' found and supported for component scanning");
    }
    catch (ClassNotFoundException ex) {
        // JSR-250 1.1 API (as included in Java EE 6) not available - simply skip.
    }
    try {
        this.includeFilters.add(new AnnotationTypeFilter(
            ((Class<? extends Annotation>) ClassUtils.forName("javax.inject.Named", cl)), false));
        logger.debug("JSR-330 'javax.inject.Named' annotation found and supported for component scanning");
    }
    catch (ClassNotFoundException ex) {
        // JSR-330 API not available - simply skip.
    }
}

6.3、获取系统运行环境

  • registry为AnnotationConfigApplicationContext,而其实现了EnvironmentCapable接口
  • 此处不再创建环境,环境已经在5.1处初始化过,可直接获取
private static Environment getOrCreateEnvironment(BeanDefinitionRegistry registry) {
    Assert.notNull(registry, "BeanDefinitionRegistry must not be null");
    // 
    if (registry instanceof EnvironmentCapable) {
        return ((EnvironmentCapable) registry).getEnvironment();
    }
    return new StandardEnvironment();
}

7、总结

  • this方法就只做一件事:初始化IOC容器AnnotationConfigApplicationContext
  系统运维 最新文章
配置小型公司网络WLAN基本业务(AC通过三层
如何在交付运维过程中建立风险底线意识,提
快速传输大文件,怎么通过网络传大文件给对
从游戏服务端角度分析移动同步(状态同步)
MySQL使用MyCat实现分库分表
如何用DWDM射频光纤技术实现200公里外的站点
国内顺畅下载k8s.gcr.io的镜像
自动化测试appium
ctfshow ssrf
Linux操作系统学习之实用指令(Centos7/8均
上一篇文章      下一篇文章      查看所有文章
加:2022-02-26 12:11:44  更:2022-02-26 12:13:12 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/16 5:27:29-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码