Object getBean(String name, Object… args) throws BeansException;

<T> T getBean(Class<T> requiredType) throws BeansException;
<T> T getBean(Class<T> requiredType, Object... args) throws BeansException;

//提供对Bean的检索,看看在IoC容器中是否有这个名字的Bean

boolean containsBean(String name);

//根据Bean的名字得到Bean实例,同时判断这个Bean是不是单例

boolean isSingleton(String name) throws NoSuchBeanDefinitionException;

boolean isPrototype(String name) throws NoSuchBeanDefinitionException;

boolean isTypeMatch(String name, ResolvableType typeToMatch) throws

NoSuchBeanDefinitionException;

boolean isTypeMatch(String name, @Nullable Class<?> typeToMatch) throws

NoSuchBeanDefinitionException;

//得到Bean实例的Class类型

@Nullable

Class<?> getType(String name) throws NoSuchBeanDefinitionException;

//得到Bean的别名,如果根据别名检索,那么其原名也会被检索出来

String[] getAliases(String name);

}

在BeanFactory里只对IoC容器的基本行为做了定义,根本不关心你的Bean是如何定义及怎样加载的。正如我们只关心能从工厂里得到什么产品,不关心工厂是怎么生产这些产品的。

要知道工厂是如何产生对象的,我们需要看具体的IoC容器实现,Spring提供了许多IoC容器实现,比如GenericApplicationContext、ClasspathXmlApplicationContext等。

ApplicationContext是Spring提供的一个高级的IoC容器,它除了能够提供IoC容器的基本功能,还为用户提供了以下附加服务。

(1)支持信息源,可以实现国际化(实现MessageSource接口)。

(2)访问资源(实现ResourcePatternResolver接口,后面章节会讲到)。

(3)支持应用事件(实现ApplicationEventPublisher接口)。

2.2. BeanDefinition


BeanDefinition 用于保存 Bean 的相关信息,包括属性、构造方法参数、依赖的 Bean 名称及是否单例、延迟加载等,它相当于实例化 Bean 的原材料,Spring 就是根据 BeanDefinition 中的信息实例化 Bean。,其继承体系如下图所示。

2.3. BeanDefinitionReader


Bean的解析过程非常复杂,功能被分得很细,因为这里需要被扩展的地方很多,必须保证足够的灵活性,以应对可能的变化。Bean的解析主要就是对Spring配置文件的解析。这个解析过程主要通过BeanDefinitionReader来完成,看看Spring中BeanDefinitionReader的类结构图,如下图所示。

通过前面的分析,我们对Spring框架体系有了一个基本的宏观了解,希望“小伙伴们”好好理解,最好在脑海中形成画面,为以后的学习打下良好的基础。

3 基于Web的IoC容器初体验


我们还是从大家最熟悉的DispatcherServlet开始,最先想到的应该是DispatcherServlet的init()方法。我们在DispatherServlet中并没有找到init()方法,经过探索,在其父类HttpServletBean中找到了,代码如下:

@Override

public final void init() throws ServletException {

if (logger.isDebugEnabled()) {

  logger.debug("Initializing servlet '" + getServletName() + "'");

}

PropertyValues pvs = new ServletConfigPropertyValues(getServletConfig(),

this.requiredProperties);

if (!pvs.isEmpty()) {

  try {
     //定位资源
     BeanWrapper bw = PropertyAccessorFactory.forBeanPropertyAccess(this);
     //加载配置信息
     ResourceLoader resourceLoader = new ServletContextResourceLoader(getServletContext());
     bw.registerCustomEditor(Resource.class, new ResourceEditor(resourceLoader, 

getEnvironment()));

     initBeanWrapper(bw);
     bw.setPropertyValues(pvs, true);
  }
  catch (BeansException ex) {
     if (logger.isErrorEnabled()) {
        logger.error("Failed to set bean properties on servlet '" + getServletName() + "'", ex);
     }
     throw ex;
  }

}

initServletBean();

if (logger.isDebugEnabled()) {

  logger.debug("Servlet '" + getServletName() + "' configured successfully");

}

}

在init()方法中,真正完成初始化容器动作的代码其实在initServletBean()方法中,我们继续跟进:

@Override

protected final void initServletBean() throws ServletException {

getServletContext().log(“Initializing Spring FrameworkServlet '” + getServletName() + “'”);

if (this.logger.isInfoEnabled()) {

  this.logger.info("FrameworkServlet '" + getServletName() + "': initialization started");

}

long startTime = System.currentTimeMillis();

try {

  this.webApplicationContext = initWebApplicationContext();
  initFrameworkServlet();

}

catch (ServletException ex) {

  this.logger.error("Context initialization failed", ex);
  throw ex;

}

catch (RuntimeException ex) {

  this.logger.error("Context initialization failed", ex);
  throw ex;

}

if (this.logger.isInfoEnabled()) {

  long elapsedTime = System.currentTimeMillis() - startTime;
  this.logger.info("FrameworkServlet '" + getServletName() + "': initialization completed 
        in " + elapsedTime + " ms");

}

}

在上面的代码中终于看到了似曾相识的代码initWebApplicationContext(),继续跟进:

protected WebApplicationContext initWebApplicationContext() {

//先从ServletContext中获得父容器WebApplicationContext

WebApplicationContext rootContext =

     WebApplicationContextUtils.getWebApplicationContext(getServletContext());

//声明子容器

WebApplicationContext wac = null;

//建立父、子容器之间的关联关系

if (this.webApplicationContext != null) {

  wac = this.webApplicationContext;
  if (wac instanceof ConfigurableWebApplicationContext) {
     ConfigurableWebApplicationContext cwac = (ConfigurableWebApplicationContext) wac;
     if (!cwac.isActive()) {
        if (cwac.getParent() == null) {
           cwac.setParent(rootContext);
        }
        configureAndRefreshWebApplicationContext(cwac);
     }
  }

}

//先去ServletContext中查找Web容器的引用是否存在,并创建好默认的空IoC容器

if (wac == null) {

  wac = findWebApplicationContext();

}

//给上一步创建好的IoC容器赋值

if (wac == null) {

  wac = createWebApplicationContext(rootContext);

}

//触发onRefresh()方法

if (!this.refreshEventReceived) {

  onRefresh(wac);

}

if (this.publishContext) {

  String attrName = getServletContextAttributeName();
  getServletContext().setAttribute(attrName, wac);
  if (this.logger.isDebugEnabled()) {
     this.logger.debug("Published WebApplicationContext of servlet '" + getServletName() +
           "' as ServletContext attribute with name \[" + attrName + "\]");
  }

}

return wac;

}

@Nullable

protected WebApplicationContext findWebApplicationContext() {

String attrName = getContextAttribute();

if (attrName == null) {

  return null;

}

WebApplicationContext wac =

     WebApplicationContextUtils.getWebApplicationContext(getServletContext(), attrName);

if (wac == null) {

  throw new IllegalStateException("No WebApplicationContext found: initializer not registered?");

}

return wac;

}

protected WebApplicationContext createWebApplicationContext(@Nullable ApplicationContext parent) {

Class<?> contextClass = getContextClass();

if (this.logger.isDebugEnabled()) {

  this.logger.debug("Servlet with name '" + getServletName() +
        "' will try to create custom WebApplicationContext context of class '" +
        contextClass.getName() + "'" + ", using parent context \[" + parent + "\]");

}

if (!ConfigurableWebApplicationContext.class.isAssignableFrom(contextClass)) {

  throw new ApplicationContextException(
        "Fatal initialization error in servlet with name '" + getServletName() +
        "': custom WebApplicationContext class \[" + contextClass.getName() +
        "\] is not of type ConfigurableWebApplicationContext");

}

ConfigurableWebApplicationContext wac =

     (ConfigurableWebApplicationContext) BeanUtils.instantiateClass(contextClass);

wac.setEnvironment(getEnvironment());

wac.setParent(parent);

String configLocation = getContextConfigLocation();

if (configLocation != null) {

  wac.setConfigLocation(configLocation);

}

configureAndRefreshWebApplicationContext(wac);

return wac;

}

protected void configureAndRefreshWebApplicationContext(ConfigurableWebApplicationContext wac) {

自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数Java工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年Java开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Java开发知识点,真正体系化!

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!

如果你觉得这些内容对你有帮助,可以扫码获取!!(备注Java获取)

img

最后

Java架构学习技术内容包含有:Spring,Dubbo,MyBatis, RPC, 源码分析,高并发、高性能、分布式,性能优化,微服务 高级架构开发等等。

还有Java核心知识点+全套架构师学习资料和视频+一线大厂面试宝典+面试简历模板可以领取+阿里美团网易腾讯小米爱奇艺快手哔哩哔哩面试题+Spring源码合集+Java架构实战电子书+2021年最新大厂面试题。
在这里插入图片描述

《互联网大厂面试真题解析、进阶开发核心学习笔记、全套讲解视频、实战项目源码讲义》点击传送门即可获取!
mmunity.csdnimg.cn/images/e5c14a7895254671a72faed303032d36.jpg" alt=“img” style=“zoom: 33%;” />

最后

Java架构学习技术内容包含有:Spring,Dubbo,MyBatis, RPC, 源码分析,高并发、高性能、分布式,性能优化,微服务 高级架构开发等等。

还有Java核心知识点+全套架构师学习资料和视频+一线大厂面试宝典+面试简历模板可以领取+阿里美团网易腾讯小米爱奇艺快手哔哩哔哩面试题+Spring源码合集+Java架构实战电子书+2021年最新大厂面试题。
[外链图片转存中…(img-qs50THVa-1713336433419)]

《互联网大厂面试真题解析、进阶开发核心学习笔记、全套讲解视频、实战项目源码讲义》点击传送门即可获取!

Logo

openvela 操作系统专为 AIoT 领域量身定制,以轻量化、标准兼容、安全性和高度可扩展性为核心特点。openvela 以其卓越的技术优势,已成为众多物联网设备和 AI 硬件的技术首选,涵盖了智能手表、运动手环、智能音箱、耳机、智能家居设备以及机器人等多个领域。

更多推荐