Spring IOC

总要再读一次Spring IOC代码吧

参考地址:https://javadoop.com

1.环境准备

java 复制代码
<dependency>  
    <groupId>org.springframework</groupId>  
    <artifactId>spring-context</artifactId>  
    <version>4.3.11.RELEASE</version>  
</dependency>

然后包被引入:

java 复制代码
ApplicationContext context = new ClassPathXmlApplicationContext("");

使用具体实现为ClassPathXmlApplicationContext,继承于ApplicationContext,父类引用指向子类。

首先,定义一个接口:

java 复制代码
public interface MessageService {
    String getMessage();
}

定义接口实现类:

java 复制代码
public class MessageServiceImpl implements MessageService {

    public String getMessage() {
        return "hello world";
    }
}

接下来,我们在 resources 目录新建一个配置文件,文件名随意,通常叫 application.xml 或 application-xxx.xml 就可以了:

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

    <bean id="messageService" class="com.javadoop.example.MessageServiceImpl"/>
</beans>

这样,我们就可以跑起来了:

java 复制代码
public class App {
    public static void main(String[] args) {
        // 用我们的配置文件来启动一个 ApplicationContext
        ApplicationContext context = new ClassPathXmlApplicationContext("classpath:application.xml");
      
        System.out.println("context 启动成功");
      
        // 从 context 中取出我们的 Bean,而不是用 new MessageServiceImpl() 这种方式
        MessageService messageService = context.getBean(MessageService.class);
        // 这句将输出: hello world
        System.out.println(messageService.getMessage());
    }
}

2.BeanFactory

核心职责:

  • 根据 name
  • 或根据 type
  • 去"取一个 Bean"

1.ListableBeanFactory

复制代码
ApplicationContext 继承了 ListableBeanFactory,这个 Listable 的意思就是,通过这个接口,我们可以获取多个 Bean,大家看源码会发现,最顶层 BeanFactory 接口的方法都是获取单个 Bean 的。
  • getBeansOfType(...):拿到某个类型的所有 Bean

  • getBeanDefinitionNames():拿到所有 Bean 名称

  • getBeanNamesForType(...):拿到某种类型对应的所有 Bean 名称

    Spring 能拿到"某种类型对应的所有 Bean 名称",本质上是因为容器内部保存了全部 Bean 的定义信息,然后在 DefaultListableBeanFactory 中遍历这些定义,逐个做类型匹配,最后把符合条

    件的 beanName 收集起来。

java 复制代码
 List<String> result = new ArrayList<>();

  for (String beanName : beanDefinitionNames) {
      BeanDefinition bd = beanDefinitionMap.get(beanName);

      if (bd.isAbstract()) {
          continue;
      }

      if (isTypeMatch(beanName, targetType)) {
          result.add(beanName);
      }

      // 如果是 FactoryBean,还要额外判断工厂本身/产品对象
  }  

2.HierarchicalBeanFactory

ApplicationContext 继承了 HierarchicalBeanFactory,Hierarchical 单词本身已经能说明问题了,也就是说我们可以在应用中起多个 BeanFactory,然后可以将各个 BeanFactory 设置为父子关系。

需要父子容器,本质上是为了"分层管理"和"复用 Bean",避免所有 Bean 都堆在一个大容器里。

比如一个大型应用里,不同模块关心的 Bean 不一样:

  • 父容器放公共 Bean:service、repository、数据源、事务管理器
  • 子容器放局部 Bean:某个 Web 模块自己的 controller、视图解析器、处理器映射器

这样做的好处是:

  • 公共能力可以复用
  • 不同层的职责更清晰
  • 子容器可以访问父容器,父容器不用感知子容器
  • 方便模块隔离,避免所有 Bean 混在一起

3.启动过程分析

设置了类配置路径之后

其中最重要的是refresh方法

java 复制代码
public void refresh() throws BeansException, IllegalStateException {  
    synchronized(this.startupShutdownMonitor) {  
        this.prepareRefresh();  
        //初始化 BeanFactory、加载 Bean、注册 Bean 等等,查看类图,这里是个返回是个beanFactory
        ConfigurableListableBeanFactory beanFactory = this.obtainFreshBeanFactory();  
        this.prepareBeanFactory(beanFactory);  
  
        try {  
            this.postProcessBeanFactory(beanFactory);  
            this.invokeBeanFactoryPostProcessors(beanFactory);  
            this.registerBeanPostProcessors(beanFactory);  
            this.initMessageSource();  
            this.initApplicationEventMulticaster();  
            this.onRefresh();  
            this.registerListeners();  
            this.finishBeanFactoryInitialization(beanFactory);  
            this.finishRefresh();  
        } catch (BeansException var9) {  
            if (this.logger.isWarnEnabled()) {  
                this.logger.warn("Exception encountered during context initialization - cancelling refresh attempt: " + var9);  
            }  
  
            this.destroyBeans();  
            this.cancelRefresh(var9);  
            throw var9;  
        } finally {  
            this.resetCommonCaches();  
        }  
  
    }  
}

其中: ConfigurableListableBeanFactory beanFactory = this.obtainFreshBeanFactory();

java 复制代码
protected ConfigurableListableBeanFactory obtainFreshBeanFactory() { 
	//刷新BeanFactory 删除旧的 创建新的 BeanFactory
    this.refreshBeanFactory();  
    //获取BeanFactory后进行返回
    ConfigurableListableBeanFactory beanFactory = this.getBeanFactory();  
    if (this.logger.isDebugEnabled()) {  
        this.logger.debug("Bean factory for " + this.getDisplayName() + ": " + beanFactory);  
    }  
  
    return beanFactory;  
}

![[Pasted image 20260331111251.png]]

java 复制代码
protected final void refreshBeanFactory() throws BeansException {  
    if (this.hasBeanFactory()) {  
        this.destroyBeans();  
        this.closeBeanFactory();  
    }  
  
    try { 
	    //ConfigurableListableBeanFactory 只有一个实现类 DefaultListableBeanFactory,而且实现类 DefaultListableBeanFactory 还通过实现右边的 AbstractAutowireCapableBeanFactory 通吃了右路。
        DefaultListableBeanFactory beanFactory = this.createBeanFactory();  
        beanFactory.setSerializationId(this.getId());  
        this.customizeBeanFactory(beanFactory);  
        this.loadBeanDefinitions(beanFactory);  
        synchronized(this.beanFactoryMonitor) {  
            this.beanFactory = beanFactory;  
        }  
    } catch (IOException ex) {  
        throw new ApplicationContextException("I/O error parsing bean definition source for " + this.getDisplayName(), ex);  
    }  
}

继续往下,看到:

java 复制代码
protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws BeansException, IOException {  
    XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);  
    beanDefinitionReader.setEnvironment(this.getEnvironment());  
    beanDefinitionReader.setResourceLoader(this);  
    beanDefinitionReader.setEntityResolver(new ResourceEntityResolver(this));  
    this.initBeanDefinitionReader(beanDefinitionReader);  
    this.loadBeanDefinitions(beanDefinitionReader);  
}

Bean加载时,将 xml 文件转换为 Document 对象

java 复制代码
protected int doLoadBeanDefinitions(InputSource inputSource, Resource resource) throws BeanDefinitionStoreException {  
    try {  
        Document doc = this.doLoadDocument(inputSource, resource);  
        return this.registerBeanDefinitions(doc, resource);  
    } catch (BeanDefinitionStoreException ex) {  
        throw ex;  
    } catch (SAXParseException ex) {  
        throw new XmlBeanDefinitionStoreException(resource.getDescription(), "Line " + ex.getLineNumber() + " in XML document from " + resource + " is invalid", ex);  
    } catch (SAXException ex) {  
        throw new XmlBeanDefinitionStoreException(resource.getDescription(), "XML document from " + resource + " is invalid", ex);  
    } catch (ParserConfigurationException ex) {  
        throw new BeanDefinitionStoreException(resource.getDescription(), "Parser configuration exception parsing XML from " + resource, ex);  
    } catch (IOException ex) {  
        throw new BeanDefinitionStoreException(resource.getDescription(), "IOException parsing XML document from " + resource, ex);  
    } catch (Throwable ex) {  
        throw new BeanDefinitionStoreException(resource.getDescription(), "Unexpected exception parsing XML document from " + resource, ex);  
    }  
}

转化为DOM树

java 复制代码
public void registerBeanDefinitions(Document doc, XmlReaderContext readerContext) {  
    this.readerContext = readerContext;  
    this.logger.debug("Loading bean definitions");  
    Element root = doc.getDocumentElement();  
    this.doRegisterBeanDefinitions(root);  
}

对Bean文件进行解析:

java 复制代码
String id = ele.getAttribute("id");  
String nameAttr = ele.getAttribute("name");  
List<String> aliases = new ArrayList();  
if (StringUtils.hasLength(nameAttr)) {  
    String[] nameArr = StringUtils.tokenizeToStringArray(nameAttr, ",; ");  
    aliases.addAll(Arrays.asList(nameArr));  
}

生成beanDefinition

AbstractBeanDefinition beanDefinition = this.parseBeanDefinitionElement(ele, beanName, containingBean);

java 复制代码
if (beanDefinition != null) {  
    if (!StringUtils.hasText(beanName)) {  
        try {  
            if (containingBean != null) {  
                beanName = BeanDefinitionReaderUtils.generateBeanName(beanDefinition, this.readerContext.getRegistry(), true);  
            } else {  
                beanName = this.readerContext.generateBeanName(beanDefinition);  
                String beanClassName = beanDefinition.getBeanClassName();  
                if (beanClassName != null && beanName.startsWith(beanClassName) && beanName.length() > beanClassName.length() && !this.readerContext.getRegistry().isBeanNameInUse(beanClassName)) {  
                    aliases.add(beanClassName);  
                }  
            }  
  
            if (this.logger.isDebugEnabled()) {  
                this.logger.debug("Neither XML 'id' nor 'name' specified - using generated bean name [" + beanName + "]");  
            }  
        } catch (Exception ex) {  
            this.error(ex.getMessage(), ele);  
            return null;  
        }  
    }  
  
    String[] aliasesArray = StringUtils.toStringArray(aliases);  
    return new BeanDefinitionHolder(beanDefinition, beanName, aliasesArray);  
} else {  
    return null;  
}

生成后,进行注册

java 复制代码
protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) {  
    BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);  
    if (bdHolder != null) {  
        bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder);  
  
        try {  
	        //bean进行注册
            BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, this.getReaderContext().getRegistry());  
        } catch (BeanDefinitionStoreException ex) {  
            this.getReaderContext().error("Failed to register bean definition with name '" + bdHolder.getBeanName() + "'", ele, ex);  
        }  
  
        this.getReaderContext().fireComponentRegistered(new BeanComponentDefinition(bdHolder));  
    }  
  
}

其中bdHolder 只包含了:

BeanDefinition 的实例和它的 beanName、aliases 这三个信息

注册部分代码:

java 复制代码
public static void registerBeanDefinition(BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry) throws BeanDefinitionStoreException {  
    String beanName = definitionHolder.getBeanName();  
	    registry.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition());  
	    //这里是要注册所有的别名,这样使用别名可以找回来
    String[] aliases = definitionHolder.getAliases();  
    if (aliases != null) {  
        for(String alias : aliases) {  
            registry.registerAlias(beanName, alias);  
        }  
    }  
  
}

注册代码:

java 复制代码
public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)

		// 将 BeanDefinition 放到这个 map 中,这个 map 保存了所有的 BeanDefinition
         this.beanDefinitionMap.put(beanName, beanDefinition);
         // 这是个 ArrayList,所以会按照 bean 配置的顺序保存每一个注册的 Bean 的名字
         this.beanDefinitionNames.add(beanName);
         // 这是个 LinkedHashSet,代表的是手动注册的 singleton bean,
         // 注意这里是 remove 方法,到这里的 Bean 当然不是手动注册的
         // 手动指的是通过调用以下方法注册的 bean :
         //     registerSingleton(String beanName, Object singletonObject)
         // 这不是重点,解释只是为了不让大家疑惑。Spring 会在后面"手动"注册一些 Bean,
         // 如 "environment"、"systemProperties" 等 bean,我们自己也可以在运行时注册 Bean 到容器中的
         this.manualSingletonNames.remove(beanName);

以上完成了Bean的注册

继续向下:

java 复制代码
preInstantiateSingletons:

for(String beanName : beanNames) {  
    RootBeanDefinition bd = this.getMergedLocalBeanDefinition(beanName);  
    if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {  
        if (this.isFactoryBean(beanName)) {  
            final FactoryBean<?> factory = (FactoryBean)this.getBean("&" + beanName);  
            boolean isEagerInit;  
            if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) {  
                isEagerInit = (Boolean)AccessController.doPrivileged(new PrivilegedAction<Boolean>() {  
                    public Boolean run() {  
                        return ((SmartFactoryBean)factory).isEagerInit();  
                    }  
                }, this.getAccessControlContext());  
            } else {  
                isEagerInit = factory instanceof SmartFactoryBean && ((SmartFactoryBean)factory).isEagerInit();  
            }  
  
            if (isEagerInit) {  
                this.getBean(beanName);  
            }  
        } else {  
            this.getBean(beanName);  
        }  
    }  
}

继续向下则是Bean的创建:

![[Pasted image 20260331160308.png]]

java 复制代码
protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, Object[] args) {  
    Class<?> beanClass = this.resolveBeanClass(mbd, beanName, new Class[0]);  
    if (beanClass != null && !Modifier.isPublic(beanClass.getModifiers()) && !mbd.isNonPublicAccessAllowed()) {  
        throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Bean class isn't public, and non-public access not allowed: " + beanClass.getName());  
    } else if (mbd.getFactoryMethodName() != null) {  
        return this.instantiateUsingFactoryMethod(beanName, mbd, args);  
    } else {  
        boolean resolved = false;  
        boolean autowireNecessary = false;  
        if (args == null) {  
            synchronized(mbd.constructorArgumentLock) {  
                if (mbd.resolvedConstructorOrFactoryMethod != null) {  
                    resolved = true;  
                    autowireNecessary = mbd.constructorArgumentsResolved;  
                }  
            }  
        }

属性注入:

java 复制代码
// bean 实例的所有属性都在这里了
   PropertyValues pvs = mbd.getPropertyValues();
   //...
   //然后先name 再type

if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME ||

mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) {

MutablePropertyValues newPvs = new MutablePropertyValues(pvs);

复制代码
  // 通过名字找到所有属性值,如果是 bean 依赖,先初始化依赖的 bean。记录依赖关系
  if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME) {
     autowireByName(beanName, mbd, bw, newPvs);
  }

  // 通过类型装配。复杂一些
  if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) {
     autowireByType(beanName, mbd, bw, newPvs);
  }

  pvs = newPvs;

}

复制代码
   然后是initializeBean 初始化,解决各种回调。


   
   
   区别非常关键:

  - populateBean:给 Bean "填属性"
  - initializeBean:对 Bean 做"初始化"

  它们是 Spring 创建 Bean 过程里的两个不同阶段。

  1. populateBean 是属性注入阶段

  这一阶段主要做:

  - 把 BeanDefinition 里的属性值设置到 Bean 实例上
  - 处理 @Autowired
  - 处理 @Value
  - 处理按名字、按类型自动注入
  - 调用 setter/反射完成依赖注入

  所以它关心的是:

  - 这个对象的成员变量、setter 属性,怎么补齐

  比如:

  userService.setOrderDao(orderDao);
  userService.setName("test");

  这些基本属于 populateBean 干的事。

  2. initializeBean 是初始化阶段

  属性都填完之后,Spring 才开始初始化 Bean。

  这一阶段主要做:

  - 调用 Aware 接口回调
  - 执行 BeanPostProcessor#postProcessBeforeInitialization
  - 调用初始化方法
  - 执行 BeanPostProcessor#postProcessAfterInitialization

  比如:

  - BeanNameAware
  - BeanFactoryAware
  - InitializingBean.afterPropertiesSet()
  - 自定义 init-method
  - AOP 代理生成,很多时候也发生在这里的后置处理器阶段

  所以它关心的是:

  - Bean 已经有完整依赖了,现在开始做"增强"和"初始化回调"

  3. 顺序上谁先谁后

  一般是:

  4. 实例化 Bean
  5. populateBean
  6. initializeBean

  也就是:

  - 先把对象造出来
  - 再把依赖注入进去
  - 最后再执行初始化逻辑

  4. 举个最直观的例子

  假设有个 Bean:

  public class UserService implements InitializingBean {
      private OrderDao orderDao;

      public void setOrderDao(OrderDao orderDao) {
          this.orderDao = orderDao;
      }

      @Override
      public void afterPropertiesSet() {
          System.out.println(orderDao); // 这里已经有值了
      }
  }

  Spring 会先执行:

  setOrderDao(...)

  这是 populateBean

  然后再执行:

  afterPropertiesSet()

  这是 initializeBean

  所以 afterPropertiesSet() 里看到的属性,通常已经注入完成了。

  5. 一句话抓本质

  populateBean 解决的是:

  - "把这个 Bean 需要的数据和依赖塞进去"

  initializeBean 解决的是:

  - "Bean 都准备好了,现在执行初始化回调和后置增强"

  一句话总结

  populateBean 是依赖注入、属性填充;initializeBean 是在属性注入完成之后,执行各种初始化回调和 Bean 后置处理。
相关推荐
魔都吴所谓1 小时前
【Linux】Ubuntu22.04 Docker+四大数据库(挂载本地)一键安装脚本
linux·数据库·docker
计算机学姐2 小时前
基于SpringBoot的奶茶店点餐系统【协同过滤推荐算法+数据可视化统计】
java·vue.js·spring boot·mysql·信息可视化·tomcat·推荐算法
@土豆2 小时前
Java JVM参数环境变量详解及SkyWalking Agent集成技术文档
java·jvm·skywalking
Yupureki2 小时前
《Linux系统编程》19.线程同步与互斥
java·linux·服务器·c语言·开发语言·数据结构·c++
又来敲代码了2 小时前
Zrlog博客的系统部署
java·linux·运维·mysql·apache·tornado
砍光二叉树2 小时前
【设计模式】行为型-责任链模式
java·设计模式·责任链模式
麦聪聊数据2 小时前
电商数据运营的最佳实践:WebSQL 如何兼顾数据分析效率与生产库安全
数据库·sql·低代码·restful
kiki_24112 小时前
用IntelliJ IDEA编写Java程序,从0到1完整教程
java·ide·intellij-idea
l1t2 小时前
试用postgresql的pg_duckdb插件
数据库·postgresql