Java教程

【spring源码-IOC】1. Spring中比较重要的类

本文主要是介绍【spring源码-IOC】1. Spring中比较重要的类,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

本系列文章旨在让小白也可以轻松学习Spring源码

本节主要学习几个类。看Spring的源码之前,需要先了解其中几个比较重要的类,这几个类也是在看源码中经常看到的类,刚开始看不懂没关系,后面遇到这些类在回来看本节会有恍然大悟的感觉。

  • DefaultListabelBeanFactory
  • XmlBeanFactory
  • AbstractAutowireCapableBeanFactory
  • ConfigurableListabelBeanFactory
  • AbstractBeanDefinition
  • BeanDefinitionReader
  • BeanDefinitionRegistry
  • BeanDefinitionHolder

一、例子

创建一个Spring的项目有很多种方式,本系列主要讲解XML配置文件的方式来注册Bean和加载。

1. 项目结构

在这里插入图片描述

1.2 Person

package beans;

/**
 * @author 环杰
 * @date 2021/07/09
 */
public class Person {

    private String name;

    private Integer age;

    public String getName() {
        return name;
    }

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

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }

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

1.3

package org.example;

import beans.Person;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

/**
 * Hello world!
 *
 */
public class App 
{
    public static void main( String[] args )
    {
        ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
        Person person = applicationContext.getBean(Person.class);
        System.out.println(person);
    }
}

1.3 App

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

    <bean id="person" class="beans.Person">
        <property name="age" value="12"/>
    </bean>
</beans>

1.4 applicationContext.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"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

    <bean id="person" class="beans.Person">
        <property name="age" value="12"/>
    </bean>
</beans>

1.5 pom.xml

其实主要是org.springframework的依赖

<?xml version="1.0" encoding="UTF-8"?>

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>

  <groupId>org.example</groupId>
  <artifactId>studySpring</artifactId>
  <version>1.0-SNAPSHOT</version>

  <name>studySpring</name>
  <!-- FIXME change it to the project's website -->
  <url>http://www.example.com</url>

  <properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <maven.compiler.source>1.7</maven.compiler.source>
    <maven.compiler.target>1.7</maven.compiler.target>
  </properties>

  <dependencies>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-context</artifactId>
      <version>5.2.15.RELEASE</version>
    </dependency>
  </dependencies>

  <build>
    <pluginManagement><!-- lock down plugins versions to avoid using Maven defaults (may be moved to parent pom) -->
      <plugins>
        <!-- clean lifecycle, see https://maven.apache.org/ref/current/maven-core/lifecycles.html#clean_Lifecycle -->
        <plugin>
          <artifactId>maven-clean-plugin</artifactId>
          <version>3.1.0</version>
        </plugin>
        <!-- default lifecycle, jar packaging: see https://maven.apache.org/ref/current/maven-core/default-bindings.html#Plugin_bindings_for_jar_packaging -->
        <plugin>
          <artifactId>maven-resources-plugin</artifactId>
          <version>3.0.2</version>
        </plugin>
        <plugin>
          <artifactId>maven-compiler-plugin</artifactId>
          <version>3.8.0</version>
        </plugin>
        <plugin>
          <artifactId>maven-surefire-plugin</artifactId>
          <version>2.22.1</version>
        </plugin>
        <plugin>
          <artifactId>maven-jar-plugin</artifactId>
          <version>3.0.2</version>
        </plugin>
        <plugin>
          <artifactId>maven-install-plugin</artifactId>
          <version>2.5.2</version>
        </plugin>
        <plugin>
          <artifactId>maven-deploy-plugin</artifactId>
          <version>2.8.2</version>
        </plugin>
        <!-- site lifecycle, see https://maven.apache.org/ref/current/maven-core/lifecycles.html#site_Lifecycle -->
        <plugin>
          <artifactId>maven-site-plugin</artifactId>
          <version>3.7.1</version>
        </plugin>
        <plugin>
          <artifactId>maven-project-info-reports-plugin</artifactId>
          <version>3.0.0</version>
        </plugin>
      </plugins>
    </pluginManagement>
  </build>
</project>

二、类图

接着讲回主题,本节前面讲解的几个类的类图如下。
在这里插入图片描述
Spring如何知道他需要注册和加载哪些Bean?那一定是根据代码来找的,那他从哪行代码开始找起?就是从
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml"); 这一行。
这一行,我们只传了 配置文件的文件名字,因此Spring一定是去解析这个配置文件,并将配置文件转换为类,根据配置文件中配置的类信息,来加载对应的类,那么现在的问题就变成了:

  • Spring如何解析配置文件
  • Spring如何根据解析后的配置文件来生成对应的bean

带着这2个问题,我们再来想。Spring中有很多Bean,这些bean要有一个池子来装,那么这个池子在Spring中我们就叫他bean工厂,想一想,鞋厂生产鞋,手套厂生产手套,bean工程生产bean,也是很合理的。
这个bean工厂在spring中有很多,但是根都是一个叫BeanFactory接口。为什么有很多个不同类型的bean工厂呢?因为创建bean的方式有很多,通过配置文件的叫XmlBeanFactory,不同类型的工厂只是增加了他一些特有的功能。比如鞋厂生产鞋,Nike鞋厂生产Nike鞋,adidas鞋厂生产adidas鞋,Nike鞋厂和adidas鞋厂的源头都是鞋厂。

  1. DefaultListableBeanFactory类在Spring中是非常非常重要的一个类。它是Spring注册及加载Bean的默认实现。
  2. XmlBeanFactory类是DefaultListableBeanFactory类的子类,对其进行了扩展,主要用于从XML配置文件中解析配置,将配置转换为BeanDefiniton
    下面是XmlBeanFactory类。
public class XmlBeanFactory extends DefaultListableBeanFactory {

	private final XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(this);
	
	public XmlBeanFactory(Resource resource) throws BeansException {
		this(resource, null);
	}
	
	public XmlBeanFactory(Resource resource, BeanFactory parentBeanFactory) throws BeansException {
		super(parentBeanFactory);
		this.reader.loadBeanDefinitions(resource);
	}

}

  1. BeanDefinitionRegistry :定义对BeanDefinition的增删改操作
  2. ConfigurableListabelBeanFactory:BeanFactory配置清单,指定忽略类型及接口等

2.1 AbstractBeanDefinition

不论我们是以配置文件Xml的方式注册Bean还是以注解@Bean的方式注册bean,最后Bean的信息都会放到AbstractBeanDefiniton中,我们在AbstractBeanDefinition的字段中会找到我们对应的配置信息。

public abstract class AbstractBeanDefinition extends BeanMetadataAttributeAccessor
		implements BeanDefinition, Cloneable {

	@Nullable
	private volatile Object beanClass;

    // bean的作用范围,对应 bean属性的scope
	@Nullable
	private String scope = SCOPE_DEFAULT;

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

	// 是否是延迟加载,bean属性的 lazy-init
	@Nullable
	private Boolean lazyInit;

	// 自动注入模式,bean属性的 autowire
	private int autowireMode = AUTOWIRE_NO;

	// 依赖检查
	private int dependencyCheck = DEPENDENCY_CHECK_NONE;

	// 用来表示一个Bean的实例化依靠另一个bean先实例化,bean属性的 depend-on
	@Nullable
	private String[] dependsOn;

	// 对应bean属性 autowire-candidate
	private boolean autowireCandidate = true;

	private boolean primary = false;

	private final Map<String, AutowireCandidateQualifier> qualifiers = new LinkedHashMap<>();

	@Nullable
	private Supplier<?> instanceSupplier;

	private boolean nonPublicAccessAllowed = true;

	private boolean lenientConstructorResolution = true;

	@Nullable
	private String factoryBeanName;

	@Nullable
	private String factoryMethodName;

	@Nullable
	private ConstructorArgumentValues constructorArgumentValues;

	@Nullable
	private MutablePropertyValues propertyValues;

	private MethodOverrides methodOverrides = new MethodOverrides();

	@Nullable
	private String initMethodName;

	@Nullable
	private String destroyMethodName;

	private boolean enforceInitMethod = true;

	private boolean enforceDestroyMethod = true;

	private boolean synthetic = false;

	private int role = BeanDefinition.ROLE_APPLICATION;

	@Nullable
	private String description;

	@Nullable
	private Resource resource;

下面我们会根据前面写的例子一步一步讲解Spring的解析和加载Bean流程。

这篇关于【spring源码-IOC】1. Spring中比较重要的类的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!