Spring IOC 源码简单分析 04 - bean的初始化

### 准备

## 目标

了解 Spring 如何初始化 bean 实例

##测试代码

gordon.study.spring.ioc.IOC04_Initialization.java

public class IOC04_Initialization {

public static void main(String[] args) {

Resource resource = new ClassPathResource("ioc/ioc04.xml");

DefaultListableBeanFactory factory = new DefaultListableBeanFactory();

BeanDefinitionReader reader = new XmlBeanDefinitionReader((BeanDefinitionRegistry) factory);

reader.loadBeanDefinitions(resource);

factory.addBeanPostProcessor(new InnerBeanPostProcessor());

InnerClass inner = factory.getBean("inner", InnerClass.class);

System.out.println("level: " + inner.level);

factory.destroySingleton("inner");

}

static class InnerBeanPostProcessor implements BeanPostProcessor {

@Override

public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {

System.out.println("in postProcessBeforeInitialization()...");

return bean;

}

@Override

public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {

System.out.println("in postProcessAfterInitialization()...");

if (bean instanceof InnerClass) {

((InnerClass) bean).level = 3;

}

return bean;

}

}

static class InnerClass implements BeanNameAware, BeanClassLoaderAware, BeanFactoryAware, InitializingBean, DisposableBean {

private int level;

public InnerClass() {

System.out.println("construct InnerClass...");

}

@Override

public void setBeanName(String name) {

System.out.println("in setBeanName()..." + name);

}

@Override

public void setBeanClassLoader(ClassLoader classLoader) {

System.out.println("in setBeanClassLoader()..." + classLoader);

}

@Override

public void setBeanFactory(BeanFactory beanFactory) throws BeansException {

System.out.println("in setBeanFactory()..." + beanFactory);

}

public void setLevel(int level) {

System.out.println("in setLevel()...");

this.level = level;

}

@Override

public void afterPropertiesSet() throws Exception {

System.out.println("in afterPropertiesSet()...");

level = 2;

}

@Override

public void destroy() throws Exception {

System.out.println("in destroy()...");

}

public void init() {

System.out.println("in init()...");

}

public void exit() {

System.out.println("in exit()...");

}

}

}

ioc04.xml

<beans ...>

<bean id="inner" class="gordon.study.spring.ioc.IOC04_Initialization$InnerClass" init-method="init" destroy-method="exit">

<property name="level" value="1" />

</bean>

</beans>

执行结果

construct InnerClass...

in setLevel()...

in setBeanName()...inner

in setBeanClassLoader()[email protected]

in setBeanFactory()...org.s[email protected]2d8f65a4: defining beans [inner]; root of factory hierarchy

in postProcessBeforeInitialization()...

in afterPropertiesSet()...

in init()...

in postProcessAfterInitialization()...

level: 3

in destroy()...

in exit()...

### 分析

## 文档描述

BeanFactory 类的文档描述了 bean 生命周期中对外提供的扩展点。

Bean factory implementations should support the standard bean lifecycle interfaces as far as possible. The full set of initialization methods and their standard order is:

  1. BeanNameAware‘s setBeanName
  2. BeanClassLoaderAware‘s setBeanClassLoader
  3. BeanFactoryAware‘s setBeanFactory
  4. EnvironmentAware‘s setEnvironment
  5. EmbeddedValueResolverAware‘s setEmbeddedValueResolver
  6. ResourceLoaderAware‘s setResourceLoader (only applicable when running in an application context)
  7. ApplicationEventPublisherAware‘s setApplicationEventPublisher (only applicable when running in an application context)
  8. MessageSourceAware‘s setMessageSource (only applicable when running in an application context)
  9. ApplicationContextAware‘s setApplicationContext (only applicable when running in an application context)
  10. ServletContextAware‘s setServletContext (only applicable when running in a web application context)
  11. postProcessBeforeInitialization methods of BeanPostProcessors
  12. InitializingBean‘s afterPropertiesSet
  13. a custom init-method definition
  14. postProcessAfterInitialization methods of BeanPostProcessors

On shutdown of a bean factory, the following lifecycle methods apply:

  1. postProcessBeforeDestruction methods of DestructionAwareBeanPostProcessors
  2. DisposableBean‘s destroy
  3. a custom destroy-method definition

## 示例代码分析

InnerClass 首先通过默认构造函数被实例化,输出 construct InnerClass...

接着装配属性,调用 setLevel 方法设置 level 属性,输出 in setLevel()...

然后就开始初始化 bean。通过 AbstractAutowireCapableBeanFactory 的 initializeBean 方法。

接着,第1620行代码处理 BeanPostProcessors 的 beforeInitialization 扩展点(11)。遍历 List<BeanPostProcessor> beanPostProcessors,调用每个 BeanPostProcessor 的 postProcessBeforeInitialization 方法。

然后,第1624行代码调用初始化方法:如果 bean 是 InitializingBean 实例,则调用 afterPropertiesSet 方法(12);如果 XML 文件中还定义了 init-method,则通过反射调用 init-method(13)。此外,Spring 框架尽力保证同一个初始化方法不会执行多次(可以尝试将 init-method 修改为 "afterPropertiesSet",看看执行结果)。

最后,第1633行代码处理BeanPostProcessors 的 afterInitialization 扩展点(14)。遍历 List<BeanPostProcessor> beanPostProcessors,调用每个 BeanPostProcessor的 postProcessAfterInitialization方法。

时间: 2024-10-02 18:49:36

Spring IOC 源码简单分析 04 - bean的初始化的相关文章

Spring IOC 源码简单分析 01 - BeanFactory

### 准备 ## 目标 了解 Spring IOC 的基础流程 ## 相关资源 Offical Doc:http://docs.spring.io/spring/docs/4.3.9.RELEASE/spring-framework-reference/htmlsingle/ Sample code:<https://github.com/gordonklg/study>,spring module 源码版本:Spring framework 4.3.9 ##测试代码 gordon.stud

Spring IoC 源码分析 (基于注解) 之 包扫描

在上篇文章Spring IoC 源码分析 (基于注解) 一我们分析到,我们通过AnnotationConfigApplicationContext类传入一个包路径启动Spring之后,会首先初始化包扫描的过滤规则.那我们今天就来看下包扫描的具体过程. 还是先看下面的代码: AnnotationConfigApplicationContext类 //该构造函数会自动扫描以给定的包及其子包下的所有类,并自动识别所有的Spring Bean,将其注册到容器中 public AnnotationConf

Spring IOC源码详解之容器依赖注入

Spring IOC源码详解之容器依赖注入 上一篇博客中介绍了IOC容器的初始化,通过源码分析大致了解了IOC容器初始化的一些知识,先简单回顾下上篇的内容 载入bean定义文件的过程,这个过程是通过BeanDefinitionReader来完成的,其中通过 loadBeanDefinition()来对定义文件进行解析和根据Spring定义的bean规则进行处理 - 事实上和Spring定义的bean规则相关的处理是在BeanDefinitionParserDelegate中完成的,完成这个处理需

Spring IoC源码解析之getBean

一.实例化所有的非懒加载的单实例Bean 从org.springframework.context.support.AbstractApplicationContext#refresh方法开发,进入到实例化所有的非懒加载的单实例Bean的finishBeanFactoryInitialization(beanFactory)的方法: protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory bea

深入Spring IOC源码之ResourceLoader

在<深入Spring IOC源码之Resource>中已经详细介绍了Spring中Resource的抽象,Resource接口有很多实现类,我们当然可以使用各自的构造函数创建符合需求的Resource实例,然而Spring提供了ResourceLoader接口用于实现不同的Resource加载策略,即将不同Resource实例的创建交给ResourceLoader来计算. public interface ResourceLoader { //classpath String CLASSPAT

Spring IOC源码详解之容器初始化

Spring IOC源码详解之容器初始化 上篇介绍了Spring IOC的大致体系类图,先来看一段简短的代码,使用IOC比较典型的代码 ClassPathResource res = new ClassPathResource("beans.xml"); DefaultListableBeanFactory factory = new DefaultListableBeanFactory(); XmlBeanDefinitionReader reader = new XmlBeanDe

Spring IOC源码详解之总体结构

Spring ICO详解之总体结构 IOC介绍 IOC, spring的核心,贯穿Spring始终.直观的来说,就是由spring来负责控制对象的生命周期和对象间的关系,将对象之间的关系抽象出来,通过spring容器控制对象生成时机,减少对象之间的耦合度. 开启Spring IOC源码学习 SpringIOC 的主要依赖源码是 spring-beans 和 spring-context两个包.前面文章中曾今讲到了如何编译spring源码,接下来将maven后的工程导入eclipse里面. 一.s

netty 源码简单分析一

周末简单看了下netty5的源码,只看懂了个大概,记录下成果,方便下次再看的时候回忆. 上服务端代码: public void run() throws Exception { EventLoopGroup bossGroup = new NioEventLoopGroup(); EventLoopGroup workerGroup = new NioEventLoopGroup(); try { ServerBootstrap b = new ServerBootstrap(); b.grou

kafka 0.8.1 新producer 源码简单分析

1 背景 最近由于项目需要,需要使用kafka的producer.但是对于c++,kafka官方并没有很好的支持. 在kafka官网上可以找到0.8.x的客户端.可以使用的客户端有C版本客户端,此客户端虽然目前看来还较为活跃,但是代码问题还是较多的,而且对于c++的支持并不是很好. 还有c++版本,虽然该客户端是按照c++的思路设计,但是最近更新时间为2013年12月19日,已经很久没有更新了. 从官方了解到,kafka作者对于现有的producer和consumer的设计是不太满意的.他们打算