Back
Featured image of post Spring源码IOC篇-BeanFactory

Spring源码IOC篇-BeanFactory

1、什么是BeanFactory

​ BeanFactory是一个工厂接口,负责生产和管理bean的一个工厂。ApplicationContext 的父接口,它才是 Spring 的核心容器, 主要的 ApplicationContext 实现都【组合】了它的功能。

2、BeanFactory功能

表面上主要方法只有getBean(),但是它实际上的职责包括:实例化、定位、配置应用程序中的对象以及建立这些对象之间的依赖。BeanFactory是一个工厂接口,Spring给出的具体实现包括DefaultListableBeanFactory、XmlBeanFactory、ApplicationContext等。

3、重要实现DefaultListableBeanFactory

DefaultListableBeanFactory是Bean工厂的一个默认实现,我们可以对它进行拓展以便实现自定义的Bean工厂。作为默认的Bean工厂实现。

从上往下开始介绍各个类以及接口的作用:

  • AliasRegistry(接口):alias指的是bean的别名,而aliasRegistry定义了对alias的增删改查等操作。
  • SimpleAliasRegistry(类):主要使用map作为alias的缓存,并对接口AliasRegistry进行实现。
  • SingletonBeanRegistry(接口):定义对单例的注册及获取。
  • BeanFactory(接口):定义获取bean及bean的各种属性。
  • DefaultSingleTonBeanRegistry(接口):实现了SingletonBeanRegistry的方法,同时继承了SimpleAliasRegistry。
  • HierarchicalBeanFactory(接口):继承BeanFactory,也就是在BeanFactory定义功能的基础上增加了对parantFactory的支持。
  • BeanDefinitionRegistry(接口):定义对BeanDefinition的增删改查功能,BeanDefinition就是描述一个bean的实例,包含了属性值(scope、bean的name、lazy加载模式等),构造参数以及其他更多的实现信息。
  • FactoryBeanRegistrySupport(类):在DefaultSingleTonBeanRegistry基础上增加了对FactoryBean的特殊功能。
  • ConfigurableBeanFactory(接口):提供配置Factory的各种方法,包括设置父工厂、bean的加载器、添加BeanPostProcessor等功能。
  • ListableBeanFactory(接口):根据各种条件获取bean的配置清单,可以根据bean的name、type等条件获得bean配置清单。
  • AbstractBeanFactory(类):综合FactoryBeanRegistrySupport和ConfigurableBeanFactory的功能。
  • AutowireCapableBeanFactory(接口):提供创建Bean、自动注入、初始化以及应用bean的后置处理器。
  • AbstractAutowireCapableBeanFactory(类):综合AbstractBeanFactory并对接口AutowireCapableBeanFactory进行实现
  • ConfigurableListableBeanFactory:BeanFactory配置清单,指定忽略类型及接口等。
  • DefaultListableBeanFactory:综合上面所有功能,主要对Bean注册后的处理。

使用DefaultListableBeanFactory来创建一些bean实例:

package com.zp.example02;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.beans.factory.support.AbstractBeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.context.annotation.AnnotationConfigUtils;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.Ordered;

import javax.annotation.Resource;

public class TestBeanFactory {
	public static void main(String[] args) {


		DefaultListableBeanFactory beanFactory=new DefaultListableBeanFactory();

		//创建Bean定义信息
		AbstractBeanDefinition beanDefinition= BeanDefinitionBuilder
				.genericBeanDefinition(Config.class)
				.setScope("singleton")
				.getBeanDefinition();

		//向bean工厂中添加bean定义信息
		beanFactory.registerBeanDefinition("config", beanDefinition);

		// 给 BeanFactory 添加一些常用的后置处理器
		AnnotationConfigUtils.registerAnnotationConfigProcessors(beanFactory);

		// BeanFactory 后置处理器主要功能,补充了一些 bean 定义
		beanFactory.getBeansOfType(BeanFactoryPostProcessor.class).values().forEach(beanFactoryPostProcessor -> {
			beanFactoryPostProcessor.postProcessBeanFactory(beanFactory);
		});

		// Bean 后置处理器, 针对 bean 的生命周期的各个阶段提供扩展, 例如 @Autowired @Resource ...
		beanFactory.getBeansOfType(BeanPostProcessor.class).values().stream()
				.sorted(beanFactory.getDependencyComparator())
				.forEach(beanPostProcessor -> {
					System.out.println(">>>>" + beanPostProcessor);
					beanFactory.addBeanPostProcessor(beanPostProcessor);
				});

		for (String name : beanFactory.getBeanDefinitionNames()) {
			System.out.println(name);
		}

		beanFactory.preInstantiateSingletons(); // 准备好所有单例
    /*
            学到了什么:
            a. beanFactory 不会做的事
                   1. 不会主动调用 BeanFactory 后处理器
                   2. 不会主动添加 Bean 后处理器
                   3. 不会主动初始化单例
                   4. 不会解析beanFactory 还不会解析 ${ } 与 #{ }
            b. bean 后处理器会有排序的逻辑
         */
		//比较CommonAnnotationBeanPostProcessor和AutowiredAnnotationBeanPostProcessor的排序优先级
		System.out.println("Common:" + (Ordered.LOWEST_PRECEDENCE - 3));
		System.out.println("Autowired:" + (Ordered.LOWEST_PRECEDENCE - 2));

	}


	@Configuration
	static class Config {
		@Bean
		public Bean1 bean1() {
			return new Bean1();
		}

		@Bean
		public Bean2 bean2() {
			return new Bean2();
		}

		@Bean
		public Bean3 bean3() {
			return new Bean3();
		}

		@Bean
		public Bean4 bean4() {
			return new Bean4();
		}
	}

	interface Inter {

	}

	static class Bean3 implements Inter {

	}

	static class Bean4 implements Inter {

	}

	static class Bean1 {

		public Bean1() {
			System.out.println("构造bean1");
		}

		@Autowired
		private Bean2 bean2;

		public Bean2 getBean2() {
			return bean2;
		}

		@Autowired
		@Resource(name = "bean4")
		private Inter bean3;

		public Inter getInter() {
			return bean3;
		}
	}

	static class Bean2 {

		public Bean2() {
			System.out.println("构造bean2");
		}
	}
}
  • beanFactory 可以通过 registerBeanDefinition 注册一个 bean definition 对象

    • 我们平时使用的配置类、xml、组件扫描等方式都是生成 bean definition 对象注册到 beanFactory 当中
    • bean definition 描述了这个 bean 的创建蓝图:scope 是什么、用构造还是工厂创建、初始化销毁方法是什么,等等
  • beanFactory 需要手动调用 beanFactory 后处理器对它做增强

    • 例如通过解析 @Bean、@ComponentScan 等注解,来补充一些 bean definition
  • beanFactory 需要手动添加 bean 后处理器,以便对后续 bean 的创建过程提供增强

    • 例如 @Autowired,@Resource 等注解的解析都是 bean 后处理器完成的
    • bean 后处理的添加顺序会对解析结果有影响,见视频中同时加 @Autowired,@Resource 的例子
  • beanFactory 需要手动调用方法来初始化单例

  • beanFactory 需要额外设置才能解析 ${} 与 #{}

4、什么是ApplicationContext

​ 由BeanFactory派生而来,提供了更多面向实际应用的功能,以一种更向面向框架的方式工作以及对上下文进行分层和实现继承。其既派生自BeanFactory也组合使用BeanFactory获取bean,并相对于BeanFactory扩展了一些功能。

我们可以看到ApplicationContext除了继承自BeanFactory接口外,还继承了额外的扩展接口分别是:MessageSource、ResourcePatternResolver、ApplicationEventPublisher、EnviromentCapable这四个接口,这四个接口就是ApplicationContext相对于BeanFactory扩展的额外的功能。

  • MessageSource:用于解析消息,并且支持消息参数化和国际化。
  • ResourcePatternResolver: 用于资源访问,例如URL和文件。
  • ApplicationEventPublisher: 用于时间发布。
  • EnviromentCapable: 整合 Environment 环境。
package com.zp.springDemo;

import com.zp.springDemo.example01.UserRegisteredEvent;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.core.env.ConfigurableEnvironment;
import org.springframework.core.io.Resource;

import java.io.IOException;
import java.util.Locale;
import java.util.Map;
import java.util.Set;

@SpringBootApplication
public class SpringDemoApplication {

	public static void main(String[] args) {
		ConfigurableApplicationContext context = SpringApplication.run(SpringDemoApplication.class, args);

		//国际化
		System.out.println("\n国际化示例--------------------------------------");
		System.out.println(context.getMessage("hi", null, Locale.CHINA));
		System.out.println(context.getMessage("hi", null, Locale.ENGLISH));
		System.out.println(context.getMessage("hi", null, Locale.JAPANESE));
		System.out.println("----------------------------------------------\n");


		//资源访问
		System.out.println("资源访问示例-------------------------------------");
		Resource[] resources = new Resource[0];
		try {
			resources = context.getResources("classpath*:META-INF/spring.factories");
		} catch (IOException e) {
			e.printStackTrace();
		}
		for (Resource resource : resources) {
			System.out.println("获取到所有的spring.factories文件为---"+resource);
		}
		System.out.println("----------------------------------------------\n");

		//事件发布
       	context.publishEvent(new UserRegisteredEvent(context));



		//环境参数
		System.out.println("获取环境参数示例----------------------------------------");
		ConfigurableEnvironment environment = context.getEnvironment();
		Map<String, Object> systemEnvironment = environment.getSystemEnvironment();
		systemEnvironment.entrySet().forEach(x->
				System.out.println("环境参数的KEY为----"+x.getKey()+"----环境参数的value为----"+x.getValue())
		);
		System.out.println("------------------------------------------------------\n");

	}

}

package com.zp.springDemo.example01;

import org.springframework.context.ApplicationEvent;

public class UserRegisteredEvent extends ApplicationEvent {
    public UserRegisteredEvent(Object source) {
        super(source);
        System.out.println("事件发布成功---------\n");
    }
}

5、ApplicationContext的一些实现

Spring 的发展历史较为悠久,因此很多资料还在讲解它较旧的实现,这里出于怀旧的原因,把它们都列出来,供大家参考

  • ClassPathXmlApplicationContext:从类路径查找 XML 配置文件,创建容器(旧)
  • FileSystemXmlApplicationContext:从磁盘路径查找 XML 配置文件,创建容器(旧)
  • XmlWebApplicationContext: 传统 SSM 整合时,基于 XML 配置文件的容器(旧)
  • AnnotationConfigWebApplicationContext:传统 SSM 整合时,基于 java 配置类的容器(旧)
  • AnnotationConfigApplicationContext: Spring boot 中非 web 环境容器(新)
  • AnnotationConfigServletWebServerApplicationContext: Spring boot 中 servlet web 环境容器(新)
  • AnnotationConfigReactiveWebServerApplicationContext: Spring boot 中 reactive web 环境容器(新)

另外要注意的是,后面这些带有 ApplicationContext 的类都是 ApplicationContext 接口的实现,但它们是组合了 DefaultListableBeanFactory 的功能,并非继承而来。