spring的BeanFactory和ApplicationContext

文中涉及的spring版本号为5.0.5

BeanFactory接口

在spring容器中,BeanFactory接口是IOC容器要实现的最基础的接口,定义了管理bean的最基本方法,例如获取实例,基本的判断等,如下图所示:
在这里插入图片描述
BeanFactory有多个子接口来进一步扩展bean相关功能的,以下与本文有直接关系,需要关注:

  1. HierarchicalBeanFactory:BeanFactory可以设置ParentBeanFactory,这个接口的两个方法都是和ParentBeanFactory相关的,getParentBeanFactory方法返回ParentBeanFactory,containsLocalBean方法是相对containsBean方法而言的,containsBean方法找不到bean的时候会通过parentBeanFactory方法去找,而containsLocalBeanFactory只在当前beanFactory找;
  2. ListableBeanFactory:主要用于获取bean的相关信息,例如获取所有bean的名称,查找指定类型的所有bean等,如下图所示:在这里插入图片描述

ApplicationContext接口

关于ApplicationContext与BeanFactory的关系,看类图即可一目了然:
在这里插入图片描述
原来ApplicationContext继承了HierarchcalBeanFactory和ListableBeanFactory,也就是说前面说的接口特性都被ApplicationContext继承下来了,另外通过类图可以发现,ApplicationContext还继承了Event,Environment,Message,resource等相关接口,也就是说除了bean的管理配置相关能力,ApplicationContext还拥有了Environment(环境),MessageSource(国际化),ResourceLoader(资源),ApplicationEventPublisher(应用事件)等服务相关的接口,简单的说ApplicationContext是以bean管理为基础的综合能力的扩展,用于满足业务对spring综合能力的需要;
再看看ApplicationContext的源码,除了继承,它自身也提供了一些扩展能力:

public interface ApplicationContext extends EnvironmentCapable, ListableBeanFactory, HierarchicalBeanFactory, MessageSource, ApplicationEventPublisher, ResourcePatternResolver {
    //标识当前context实例id
    @Nullable
    String getId();
	//返回当前context所属的应用名称,默认为空字符串,在web应用中返回的是servlet的contextPath
    String getApplicationName();
    //返回当前context的名称
    String getDisplayName();
	//返回context第一次被加载的时间
    long getStartupDate();
    //返回当前context的Parent
    @Nullable
    ApplicationContext getParent();
	//返回具有自动装配能力的beanFactory,默认返回的就是初始化时实例化的beanFactory
    AutowireCapableBeanFactory getAutowireCapableBeanFactory() throws IllegalStateException;
}

小结:

  1. beanFactory是基础,BeanFactory和它的子接口定义的API满足了spring环境中对bean管理和配置需求;
  2. ApplicationContext是扩展,以BeanFactory为主线,通过继承的方式综合了环境,国际化,资源,应用事件等多条支线,自己又规定了一些扩展服务(如返回context的id,应用名称等),而所有支线都以bean服务为基础;

实现类解析

如果有个类实现了ApplicationContext接口,那必须实现上述多个接口定义的方法,那这个类岂不是很复杂?我们来看看AbstractApplicationContext类的源码,这是个基础抽象类,常用的ClassPathXmlApplicationContext,AnnotationConfigWebApplicationContext等继承了AbstractApplicationContext;
先看看是如何实现BeanFactory接口中定义的方法的:

	@Override
	public Object getBean(String name, Object... args) throws BeansException {
		assertBeanFactoryActive();
		return getBeanFactory().getBean(name, args);
	}

	@Override
	public <T> T getBean(Class<T> requiredType) throws BeansException {
		assertBeanFactoryActive();
		return getBeanFactory().getBean(requiredType);
	}

	@Override
	public <T> T getBean(Class<T> requiredType, Object... args) throws BeansException {
		assertBeanFactoryActive();
		return getBeanFactory().getBean(requiredType, args);
	}

	@Override
	public <T> ObjectProvider<T> getBeanProvider(Class<T> requiredType) {
		assertBeanFactoryActive();
		return getBeanFactory().getBeanProvider(requiredType);
	}

看过上述代码后恍然大悟,原来AbstractApplicationContext并没有自己来完成bean的管理配置,而是全部委派给getBeanFactory()方法返回的实例,接口是组合,实现也是组合,这种清晰的设计是学习的典范;
在看看getBeanFactory方法,解释究竟是谁在真正提供bean的管理配置服务,该方法的实现在子类AbstractRefreshableApplicationContext中,代码很简单,返回了成员变量beanFactory:

	@Override
	public final ConfigurableListableBeanFactory getBeanFactory() {
		synchronized (this.beanFactoryMonitor) {
			if (this.beanFactory == null) {
				throw new IllegalStateException("BeanFactory not initialized or already closed - " +
						"call 'refresh' before accessing beans via the ApplicationContext");
			}
			return this.beanFactory;
		}
	}

该成员变量在refreshBeanFactory方法中实例化,而refreshBeanFactory方法又是在spring容器初始化的时候调用,所以容器初始化之后,AbstractApplicationContext就具备了bean管理配置的能力;

扩展思维

看了AbstractApplicationContext类中BeanFactory的相关代码,我就猜想:莫非Message支线也是这个套路,委托给Message服务相关实例来完成?看代码吧:

@Override
	public String getMessage(String code, @Nullable Object[] args, Locale locale) throws NoSuchMessageException {
		return getMessageSource().getMessage(code, args, locale);
	}

	@Override
	public String getMessage(MessageSourceResolvable resolvable, Locale locale) throws NoSuchMessageException {
		return getMessageSource().getMessage(resolvable, locale);
	}

如上述代码所示:Message相关接口实现,都是getMessageSource()方法返回的实例在承担,getMessageSource()方法返回的是成员变量messageSource,该成员变量也是在spring容器初始化的时候,调用initMessageSource()方法生成的;
至此,通过查看源码,我们对spring的beanFactory和ApplicationContext有了更清晰的认识,又结合了类图分析源码的实践。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值