7.1Spring IoC容器与应用上下文的设计与实现

1. SpringIOC容器的设计

SpringIOC设计分为两条线。

  1. BeanFactroy==>HierachicalBeaFactroy==>ConfirationBeaFactroy 这条线可以理解成为SpringIOC容器的设计路线。
  2. BeanFactroy==>ListableBeanFactory==>ApplicationContext==>ConfigrableApplicationContext 这条是Spring上下文的设计路线。

之所以要这样分两条线,主要是要将容器和上下文区分开来。因为在Spring项目中,上下文对容器不仅是扩展关系,更重要的事持有关系,上下文是以属性的形式持有容器,开发者可以通过上下文对象获取容器。作者比较倾向于将二者区分开来理解,当然也可以理解上下文是容器的高级表现形式。
容器和IOC的实现路线

1.1 IOC 容器的设计路线

BeanFactory 定义了IOC容器的基本规范,包括getBean()按类型和名称获取Bean的方法。

BeanFactoryHierarchicalBeanFactory

HIerarchicalBeanFactory是在BeanFactory增加了getParentBeanFactory()方法,使BeanFactory具备了双亲IOC管理的功能。
ConfigurableBeanFactory接口是提供了配置BeanFactory的各种方法。比如setParentBeanFactroy()方法,配置上面提到的双亲IOC容器,addBeanProcessor()方法,配置Bean后置处理器等。

到ConfigurableBeanFactory接口为止,IOC容器还没有作为容器最基本的功能,那就是装东西。

1.2 应用上下问设计路线

上面说了应用上下文是IOC容器的高级表现形式,ListableBeanFactory具备了操作BeanDefinition的能力,比如getBeanDefinition()方法,可以获取Bean的总数。ApplicationContext类,实现的接口 如图所示:

ApplicationContext实现的接口

  1. MessageRourse,支持不同的信息源。具备支持国际化的实现,为了开发多语言版本提供服务。
  2. ResourcePatternResolver,访问数据源,具备了从不同地方得到的Bean定义资源的能力,比如 xml、java config、注释 等等。
  3. ApplicationEventPublisher,发布事件。使应用上下文具备了事件的机制,事件机制为Bean声明周期的管理提供了便利。

WebApplicationContext 扩展了对Web应用的支持。

ConfigurableApplicationContext其中定义了一个重要的方法refresh方法。ConfigurableApplicationContext最重要的事扩展了配置上下文的功能,可控制上下文生命周期的能力等。

ConfigurableApplicationContext

2. IOC容器的具体实现类DefaultListableBeanFactory

首先证明一点,为什么说DefaultListableBeanFactory类是具体的实现类。
随便启动一个SpringBoot项目找到getSpringFactoriesInstances代码那一行

	/**
	 * Run the Spring application, creating and refreshing a new
	 * {@link ApplicationContext}.
	 * @param args the application arguments (usually passed from a Java main method)
	 * @return a running {@link ApplicationContext}
	 */
	public ConfigurableApplicationContext run(String... args) {
		// 记录程序运行时间
		StopWatch stopWatch = new StopWatch();
		stopWatch.start();
		// ConfigrableApplicationContext Spring的上下文
		ConfigurableApplicationContext context = null;
		Collection<SpringBootExceptionReporter> exceptionReporters = new ArrayList<>();
		configureHeadlessProperty();
		// 从MEATE-INFO/spring.factories中获取监听器
		SpringApplicationRunListeners listeners = getRunListeners(args);
		// 1.获取并启动监听器
		listeners.starting();
		try {
			ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
			// 2. 构造容器环境
			ConfigurableEnvironment environment = prepareEnvironment(listeners, applicationArguments);
			// 处理需要忽略的Bean 
			configureIgnoreBeanInfo(environment);
			// 打印banner
			Banner printedBanner = printBanner(environment);
			// 初始化容器
			context = createApplicationContext();
			// 实例化SpringBootExceptionReporter.class,用来支持报告关于启动的错误
			exceptionReporters = getSpringFactoriesInstances(SpringBootExceptionReporter.class,
					new Class[] { ConfigurableApplicationContext.class }, context);
			// 4.刷新容器前的准备阶段
			prepareContext(context, environment, listeners, applicationArguments, printedBanner);
			// 5.刷新容器
			refreshContext(context);
			// 刷新容器后的扩展接口
			afterRefresh(context, applicationArguments);
			stopWatch.stop();
			if (this.logStartupInfo) {
				new StartupInfoLogger(this.mainApplicationClass).logStarted(getApplicationLog(), stopWatch);
			}
			listeners.started(context);
			callRunners(context, applicationArguments);
		}
		catch (Throwable ex) {
			handleRunFailure(context, ex, exceptionReporters, listeners);
			throw new IllegalStateException(ex);
		}

		try {
			listeners.running(context);
		}
		catch (Throwable ex) {
			handleRunFailure(context, ex, exceptionReporters, null);
			throw new IllegalStateException(ex);
		}
		return context;
	}

DefaultListableBeanFactory
IoC容器的真实面孔就是这个DefaultListableBeanFactory,它还有一个子类XmlBeanFactory,不过都已经被标注为弃用了。

XmlBeanFactory

DefaultListableBeanFactory继承和实现

2.1 作为IOC 容器的基础设计路线

DefaultListableBeanFactoryConfigurableListableBeanFactory接口主要是增加指定忽略类型和接口等

ConfigurableListableBeanFactory

2.2 作为IOC容器的高级路线

IOC高级设计路线

  1. 设计路线:
BeanFactory => AutowireCapableBeanFactory =>AbstractAutowireCapableBeanFactory == DefaultListableBeanFactory

在这条线路中,AutowireCapableBeanFactory接口定义了自动注入bean(autowireBean())创建bean(createBean()) ,初始化bean(initializeBean())方法等。那么真正实现这些方法的类便是 AbstractAutowireCapableBeanFactory()。

AbsrtactAutoCapableBeanFactroy抽闲类中实现了AutoCapableBeanFactory接口定义的方法。在此基础上通过继承AbstractBeanFactory具备了操作Bean的能力。

SingletonBeanRegistry=>DefaultSingletonBeanRegistry=>FactoryBeanRegistrySupper=>AbstractBeanFactory=>AutowireCapableBeanFactory => DefaultListableBeanFactory

这个关系链中重点是SingletonBeanRegistry接口顾名思义,除了注册单例之外,还定义获取单例的方法。

注意:为什么只有 singleton的注册中心,而没有prototype类型的Bean的注册中心?因为单例Bean(singleton)是Spring帮我们创建并维护的,原型Bean(prototype) 是每次获取都会创建出来实例,本质是不同的。

SingletonBeanRegistry
3.

AliasRegistry=>SimpleAliasRegistry=>DefaultSingletonBeanRegistry=>FactroyBeanRegistry=>AbstractBeanFactory=>AutowireCapableBeanFactory=>DefaultListableBeanFactory

这条路线主要提供管理别称的能力。

AliasRegistry=>BeanDefinitionRegistry=>DefaultListableBeanFactory

BeanDefinitionRegistry接口是注册中心,使DefaultListableBeanFactory具备操作Beandefinition的能力。

BeanDefinitionRegistry

2.3 DefaultListableBeanFactory几个重要的父类和接口

2.3.1 AbstractBeanFactory 抽象类

AbstractBeanFactory如上图所示,AbstarctBeanFactory中定义的几个重要方法 @Autowired @Resource(name = “xxx”) 一个是按类型获取一个是按名获取,具体的实现就是按照图上圈的几个方法。几个getBean()方法最终都是进入到doGetBean()方法,doGetBean()方法是实际获得bean的地方,也就是触发依赖注入的地方。

2.3.2 AbstractAutowireCapableBeanFactory抽象类

AbstractBeanFactory中实现类getBean()方法AbstractAutowireCapableBeanFactory中实现了bean的创建方法。
当我们需要定义一个Bean通常会这样写 @Bean(name=“test”,initMethod=“init”,destoryMethod=“destory”)
AbstractAutowireCapableBeanFactory中完成了一个Bean从create(createBean()) => createInstance(createBeanInstance()) => init(invokeInitMethods()) 的所有工作。所以这个抽象类的作用不言而喻。

2.3.3 DefaultSigletonBeanFactoryRegistry让IOC容器具有容器能力

通常理解的Spring容器,这个容器其实更多的是BeanFactory代表的意义:Bean的生产工厂,我们通常理解的容器就是用来装东西的,但是Spring容器不是代表类似现实中容器一样的东西,而是更像一个生产工厂,生产东西的地方,比如我们需要一个bean,只需要告诉Spring,它就会给我们,所以到现在为止我们还没有看到Spring的"容器"能力。

DefaultSingletonBeanRegistry属性如下

public class DefaultSingletonBeanRegistry extends SimpleAliasRegistry implements SingletonBeanRegistry {

	/** Cache of singleton objects: bean name to bean instance. */
	private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256);

	/** Cache of singleton factories: bean name to ObjectFactory. */
	private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<>(16);

	/** Cache of early singleton objects: bean name to bean instance. */
	private final Map<String, Object> earlySingletonObjects = new HashMap<>(16);

	/** Set of registered singletons, containing the bean names in registration order. */
	private final Set<String> registeredSingletons = new LinkedHashSet<>(256);

	/** Names of beans that are currently in creation. */
	private final Set<String> singletonsCurrentlyInCreation =
			Collections.newSetFromMap(new ConcurrentHashMap<>(16));

	/** Names of beans currently excluded from in creation checks. */
	private final Set<String> inCreationCheckExclusions =
			Collections.newSetFromMap(new ConcurrentHashMap<>(16));

	/** List of suppressed Exceptions, available for associating related causes. */
	@Nullable
	private Set<Exception> suppressedExceptions;

	/** Flag that indicates whether we're currently within destroySingletons. */
	private boolean singletonsCurrentlyInDestruction = false;

	/** Disposable bean instances: bean name to disposable instance. */
	private final Map<String, Object> disposableBeans = new LinkedHashMap<>();

	/** Map between containing bean names: bean name to Set of bean names that the bean contains. */
	private final Map<String, Set<String>> containedBeanMap = new ConcurrentHashMap<>(16);

	/** Map between dependent bean names: bean name to Set of dependent bean names. */
	private final Map<String, Set<String>> dependentBeanMap = new ConcurrentHashMap<>(64);

	/** Map between depending bean names: bean name to Set of bean names for the bean's dependencies. */
	private final Map<String, Set<String>> dependenciesForBeanMap = new ConcurrentHashMap<>(64);
	}

属性singletonObjects,就是这个属性最终存储单例(singleton)bean的地方

DefaultSingletonBeanRegistry上面提到的SingletonBeanRegsitry接口的相关方法,并且增加了很多对单例的操作方法。

2.3.4 DefaultListableBeanFactory

上面重IOC容器的宏观设计角度阐述了DefaultListableBeanFactory作为IOC容器的具体实现的设计思想。

以下是DefaultListableBeanFactory的属性

	/** Map from serialized id to factory instance. */
	// 缓存 序列化IDdao1 DefaultListableBeanFactory 实例的映射
	private static final Map<String, Reference<DefaultListableBeanFactory>> serializableFactories =
			new ConcurrentHashMap<>(8);

	/** Optional id for this factory, for serialization purposes. */
	@Nullable
	private String serializationId;

	/** Whether to allow re-registration of a different definition with the same name. */
	private boolean allowBeanDefinitionOverriding = true;

	/** Whether to allow eager class loading even for lazy-init beans. */
	private boolean allowEagerClassLoading = true;

	/** Optional OrderComparator for dependency Lists and arrays. */
	@Nullable
	private Comparator<Object> dependencyComparator;

	/** Resolver to use for checking if a bean definition is an autowire candidate. */
	// 被用来去解决校验一个bean的定义是不是自动装载的候选
	private AutowireCandidateResolver autowireCandidateResolver = new SimpleAutowireCandidateResolver();

	/** Map from dependency type to corresponding autowired value. */
	private final Map<Class<?>, Object> resolvableDependencies = new ConcurrentHashMap<>(16);

	/** Map of bean definition objects, keyed by bean name. */
	private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<>(256);2

	/** Map of singleton and non-singleton bean names, keyed by dependency type. */
	private final Map<Class<?>, String[]> allBeanNamesByType = new ConcurrentHashMap<>(64);

	/** Map of singleton-only bean names, keyed by dependency type. */
	private final Map<Class<?>, String[]> singletonBeanNamesByType = new ConcurrentHashMap<>(64);

	/** List of bean definition names, in registration order. */
	private volatile List<String> beanDefinitionNames = new ArrayList<>(256);

	/** List of names of manually registered singletons, in registration order. */
	private volatile Set<String> manualSingletonNames = new LinkedHashSet<>(16);

	/** Cached array of bean definition names in case of frozen configuration. */
	@Nullable
	private volatile String[] frozenBeanDefinitionNames;

	/** Whether bean definition metadata may be cached for all beans. */
	private volatile boolean configurationFrozen = false;

在Spring中,实际上是把DefaultListableBeanFactory作为一个默认功能完整的IOC容器来使用。DefaultListableBeanFactroy作为一个功能完整的容器具备了除以上父类所具有功能外,还加入对BeanDefinition的管理和维护。从上面的代码可以看到一个重要的属性:BeanDefinitionMap。
beanDefinitionMap缓存了Bean name到 BeanDefinition的映射。到这里是不是发现了Ioc容器另外一个作为"容器"的能力,总结一下这两个能力一个是装单例 (Singleton)Bean,一个是装BeanDefinition。

2.3.5 BeanDefinition

Spring通过定义BeanDefinition来管理基于Spring的应用中的各种对象以及他们之间的相互依赖关系。
BeanDefintion抽象了我们对Bean的定义,是让容器起作用的主要数据类型。在计算机世界里,所有的功能都是建立在通过数据对实现进行抽象的基础之上的。IOC容器是用来管理对象依赖关系的,对IOC容器来说,BeanDefinition就是对依赖反转模式中管理的对象依赖关系的数据抽象,也是容器实现依赖反转的数据结构,依赖反转功能都是围绕这个BeanDefinition的处理来完成的。这些BeanDefinition就像容器里装的水,有了这些基本数据,容器才能发挥作用。简单一句话来说,BeanDefintion就是Bean的元数据,BeanDefinition存放了对象Bean的基本描述,包括Bean有什么属性、方法、Bean的位置等等Bean的各种信息、IOC容器可以通过BeanDefinition生成Bean。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值