Spring框架系列(8) – Spring IOC实现原理详解之Bean实例化(生命周期,循环依赖等)

虚幻大学 xuhss 174℃ 0评论

? 优质资源分享 ?

学习路线指引(点击解锁) 知识定位 人群定位
? Python实战微信订餐小程序 ? 进阶级 本课程是python flask+微信小程序的完美结合,从项目搭建到腾讯云部署上线,打造一个全栈订餐系统。
?Python量化交易实战? 入门级 手把手带你打造一个易扩展、更安全、效率更高的量化交易系统

作者:@pdai本文为作者原创,转载请注明出处:https://blog.csdn.net/pengdai/p/16421879.html


内容目录


上文,我们看了IOC设计要点和设计结构;以及Spring如何实现将资源配置(以xml配置为例)通过加载,解析,生成BeanDefination并注册到IoC容器中的;容器中存放的是Bean的定义即BeanDefinition放到beanDefinitionMap中,本质上是一个ConcurrentHashMap;并且BeanDefinition接口中包含了这个类的Class信息以及是否是单例等。那么如何从BeanDefinition中实例化Bean对象呢,这是本文主要研究的内容?@pdai

引入

上文,我们看了IOC设计要点和设计结构;以及Spring如何实现将资源配置(以xml配置为例)通过加载,解析,生成BeanDefination并注册到IoC容器中的;容器中存放的是Bean的定义即BeanDefinition放到beanDefinitionMap中,本质上是一个ConcurrentHashMap;并且BeanDefinition接口中包含了这个类的Class信息以及是否是单例等。那么如何从BeanDefinition中实例化Bean对象呢?

本文主要研究如何从IOC容器已有的BeanDefinition信息,实例化出Bean对象;这里还会包括三块重点内容:

  • BeanFactory中getBean的主体思路
  • Spring如何解决循环依赖问题
  • Spring中Bean的生命周期

5c246de90f53ca79c4ce087c3f0b744f - Spring框架系列(8) - Spring IOC实现原理详解之Bean实例化(生命周期,循环依赖等)

BeanFactory中getBean的主体思路

上文中我们知道BeanFactory定义了Bean容器的规范,其中包含根据bean的名字, Class类型和参数等来得到bean实例。

// 根据bean的名字和Class类型等来得到bean实例 
Object getBean(String name) throws BeansException;    
Object getBean(String name, Class requiredType) throws BeansException;    
Object getBean(String name, Object... args) throws BeansException;
 T getBean(Class requiredType) throws BeansException;
 T getBean(Class requiredType, Object... args) throws BeansException;

初步的思考

上文我们已经分析了IoC初始化的流程,最终的将Bean的定义即BeanDefinition放到beanDefinitionMap中,本质上是一个ConcurrentHashMap;并且BeanDefinition接口中包含了这个类的Class信息以及是否是单例等;

052be59d891eff34dda499bbae234855 - Spring框架系列(8) - Spring IOC实现原理详解之Bean实例化(生命周期,循环依赖等)

这样我们初步有了实现Object getBean(String name)这个方法的思路:

  • 从beanDefinitionMap通过beanName获得BeanDefinition
  • 从BeanDefinition中获得beanClassName
  • 通过反射初始化beanClassName的实例instance
    • 构造函数从BeanDefinition的getConstructorArgumentValues()方法获取
    • 属性值从BeanDefinition的getPropertyValues()方法获取
  • 返回beanName的实例instance

由于BeanDefinition还有单例的信息,如果是无参构造函数的实例还可以放在一个缓存中,这样下次获取这个单例的实例时只需要从缓存中获取,如果获取不到再通过上述步骤获取。

(PS:如上只是我们初步的思路,而Spring还需要考虑各种设计上的问题,比如beanDefinition中其它定义,循环依赖等;所以我们来看下Spring是如何是如何实现的)

Spring中getBean的主体思路

BeanFactory实现getBean方法在AbstractBeanFactory中,这个方法重载都是调用doGetBean方法进行实现的:

public Object getBean(String name) throws BeansException {
  return doGetBean(name, null, null, false);
}
public  T getBean(String name, Class requiredType) throws BeansException {
 return doGetBean(name, requiredType, null, false);
}
public Object getBean(String name, Object... args) throws BeansException {
 return doGetBean(name, null, args, false);
}
public  T getBean(String name, @Nullable Class requiredType, @Nullable Object... args)
 throws BeansException {
 return doGetBean(name, requiredType, args, false);
}

我们来看下doGetBean方法(这个方法很长,我们主要看它的整体思路和设计要点):

// 参数typeCheckOnly:bean实例是否包含一个类型检查
protected  T doGetBean(
 String name, @Nullable Class requiredType, @Nullable Object[] args, boolean typeCheckOnly)
 throws BeansException {

 // 解析bean的真正name,如果bean是工厂类,name前缀会加&,需要去掉
 String beanName = transformedBeanName(name);
 Object beanInstance;

 // Eagerly check singleton cache for manually registered singletons.
 Object sharedInstance = getSingleton(beanName);
 if (sharedInstance != null && args == null) {
 // 无参单例从缓存中获取
 beanInstance = getObjectForBeanInstance(sharedInstance, name, beanName, null);
 }

 else {
 // 如果bean实例还在创建中,则直接抛出异常
 if (isPrototypeCurrentlyInCreation(beanName)) {
 throw new BeanCurrentlyInCreationException(beanName);
 }

 // 如果 bean definition 存在于父的bean工厂中,委派给父Bean工厂获取
 BeanFactory parentBeanFactory = getParentBeanFactory();
 if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
 // Not found -> check parent.
 String nameToLookup = originalBeanName(name);
 if (parentBeanFactory instanceof AbstractBeanFactory) {
 return ((AbstractBeanFactory) parentBeanFactory).doGetBean(
 nameToLookup, requiredType, args, typeCheckOnly);
 }
 else if (args != null) {
 // Delegation to parent with explicit args.
 return (T) parentBeanFactory.getBean(nameToLookup, args);
 }
 else if (requiredType != null) {
 // No args -> delegate to standard getBean method.
 return parentBeanFactory.getBean(nameToLookup, requiredType);
 }
 else {
 return (T) parentBeanFactory.getBean(nameToLookup);
 }
 }

 if (!typeCheckOnly) {
 // 将当前bean实例放入alreadyCreated集合里,标识这个bean准备创建了
 markBeanAsCreated(beanName);
 }

 StartupStep beanCreation = this.applicationStartup.start("spring.beans.instantiate")
 .tag("beanName", name);
 try {
 if (requiredType != null) {
 beanCreation.tag("beanType", requiredType::toString);
 }
 RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
 checkMergedBeanDefinition(mbd, beanName, args);

 // 确保它的依赖也被初始化了.
 String[] dependsOn = mbd.getDependsOn();
 if (dependsOn != null) {
 for (String dep : dependsOn) {
 if (isDependent(beanName, dep)) {
 throw new BeanCreationException(mbd.getResourceDescription(), beanName,
 "Circular depends-on relationship between '" + beanName + "' and '" + dep + "'");
 }
 registerDependentBean(dep, beanName);
 try {
 getBean(dep); // 初始化它依赖的Bean
 }
 catch (NoSuchBeanDefinitionException ex) {
 throw new BeanCreationException(mbd.getResourceDescription(), beanName,
 "'" + beanName + "' depends on missing bean '" + dep + "'", ex);
 }
 }
 }

 // 创建Bean实例:单例
 if (mbd.isSingleton()) {
 sharedInstance = getSingleton(beanName, () -> {
 try {
 // 真正创建bean的方法
 return createBean(beanName, mbd, args);
 }
 catch (BeansException ex) {
 // Explicitly remove instance from singleton cache: It might have been put there
 // eagerly by the creation process, to allow for circular reference resolution.
 // Also remove any beans that received a temporary reference to the bean.
 destroySingleton(beanName);
 throw ex;
 }
 });
 beanInstance = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
 }
 // 创建Bean实例:原型
 else if (mbd.isPrototype()) {
 // It's a prototype -> create a new instance.
 Object prototypeInstance = null;
 try {
 beforePrototypeCreation(beanName);
 prototypeInstance = createBean(beanName, mbd, args);
 }
 finally {
 afterPrototypeCreation(beanName);
 }
 beanInstance = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
 }
 // 创建Bean实例:根据bean的scope创建
 else {
 String scopeName = mbd.getScope();
 if (!StringUtils.hasLength(scopeName)) {
 throw new IllegalStateException("No scope name defined for bean ´" + beanName + "'");
 }
 Scope scope = this.scopes.get(scopeName);
 if (scope == null) {
 throw new IllegalStateException("No Scope registered for scope name '" + scopeName + "'");
 }
 try {
 Object scopedInstance = scope.get(beanName, () -> {
 beforePrototypeCreation(beanName);
 try {
 return createBean(beanName, mbd, args);
 }
 finally {
 afterPrototypeCreation(beanName);
 }
 });
 beanInstance = getObjectForBeanInstance(scopedInstance, name, beanName, mbd);
 }
 catch (IllegalStateException ex) {
 throw new ScopeNotActiveException(beanName, scopeName, ex);
 }
 }
 }
 catch (BeansException ex) {
 beanCreation.tag("exception", ex.getClass().toString());
 beanCreation.tag("message", String.valueOf(ex.getMessage()));
 cleanupAfterBeanCreationFailure(beanName);
 throw ex;
 }
 finally {
 beanCreation.end();
 }
 }

 return adaptBeanInstance(name, beanInstance, requiredType);
}
折叠 

这段代码很长,主要看我加中文注释的方法即可。

  • 解析bean的真正name,如果bean是工厂类,name前缀会加&,需要去掉
  • 无参单例先从缓存中尝试获取
  • 如果bean实例还在创建中,则直接抛出异常
  • 如果bean definition 存在于父的bean工厂中,委派给父Bean工厂获取
  • 标记这个beanName的实例正在创建
  • 确保它的依赖也被初始化
  • 真正创建
    • 单例时
    • 原型时
    • 根据bean的scope创建

重点:Spring如何解决循环依赖问题

首先我们需要说明,Spring只是解决了单例模式下属性依赖的循环问题;Spring为了解决单例的循环依赖问题,使用了三级缓存。

Spring单例模式下的属性依赖

先来看下这三级缓存

/** Cache of singleton objects: bean name --> bean instance */
private final Map singletonObjects = new ConcurrentHashMap(256);

/** Cache of early singleton objects: bean name --> bean instance */
private final Map earlySingletonObjects = new HashMap(16);

/** Cache of singleton factories: bean name --> ObjectFactory */
private final Map> singletonFactories = new HashMap>(16);
  • 第一层缓存(singletonObjects):单例对象缓存池,已经实例化并且属性赋值,这里的对象是成熟对象
  • 第二层缓存(earlySingletonObjects):单例对象缓存池,已经实例化但尚未属性赋值,这里的对象是半成品对象
  • 第三层缓存(singletonFactories): 单例工厂的缓存

如下是获取单例中

protected Object getSingleton(String beanName, boolean allowEarlyReference) {
  // Spring首先从singletonObjects(一级缓存)中尝试获取
  Object singletonObject = this.singletonObjects.get(beanName);
  // 若是获取不到而且对象在建立中,则尝试从earlySingletonObjects(二级缓存)中获取
  if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
    synchronized (this.singletonObjects) {
        singletonObject = this.earlySingletonObjects.get(beanName);
        if (singletonObject == null && allowEarlyReference) {
          ObjectFactory singletonFactory = this.singletonFactories.get(beanName);
          if (singletonFactory != null) {
            //若是仍是获取不到而且容许从singletonFactories经过getObject获取,则经过singletonFactory.getObject()(三级缓存)获取
              singletonObject = singletonFactory.getObject();
              //若是获取到了则将singletonObject放入到earlySingletonObjects,也就是将三级缓存提高到二级缓存中
              this.earlySingletonObjects.put(beanName, singletonObject);
              this.singletonFactories.remove(beanName);
          }
        }
    }
  }
  return (singletonObject != NULL_OBJECT ? singletonObject : null);
}

补充一些方法和参数

  • isSingletonCurrentlyInCreation():判断当前单例bean是否正在建立中,也就是没有初始化完成(好比A的构造器依赖了B对象因此得先去建立B对象, 或则在A的populateBean过程当中依赖了B对象,得先去建立B对象,这时的A就是处于建立中的状态。)
  • allowEarlyReference :是否容许从singletonFactories中经过getObject拿到对象

分析getSingleton()的整个过程,Spring首先从一级缓存singletonObjects中获取。若是获取不到,而且对象正在建立中,就再从二级缓存earlySingletonObjects中获取。若是仍是获取不到且容许singletonFactories经过getObject()获取,就从三级缓存singletonFactory.getObject()(三级缓存)获取,若是获取到了则从三级缓存移动到了二级缓存。

从上面三级缓存的分析,咱们能够知道,Spring解决循环依赖的诀窍就在于singletonFactories这个三级cache。这个cache的类型是ObjectFactory,定义以下:

public interface ObjectFactory {
 T getObject() throws BeansException;
}

在bean建立过程当中,有两处比较重要的匿名内部类实现了该接口。一处是Spring利用其建立bean的时候,另外一处就是:

addSingletonFactory(beanName, new ObjectFactory() {
 @Override public Object getObject() throws BeansException {
 return getEarlyBeanReference(beanName, mbd, bean);
 }});

此处就是解决循环依赖的关键,这段代码发生在createBeanInstance以后,也就是说单例对象此时已经被建立出来的。这个对象已经被生产出来了,虽然还不完美(尚未进行初始化的第二步和第三步),可是已经能被人认出来了(根据对象引用能定位到堆中的对象),因此Spring此时将这个对象提早曝光出来让你们认识,让你们使用。

好比“A对象setter依赖B对象,B对象setter依赖A对象”,A首先完成了初始化的第一步,而且将本身提早曝光到singletonFactories中,此时进行初始化的第二步,发现本身依赖对象B,此时就尝试去get(B),发现B尚未被create,因此走create流程,B在初始化第一步的时候发现本身依赖了对象A,因而尝试get(A),尝试一级缓存singletonObjects(确定没有,由于A还没初始化彻底),尝试二级缓存earlySingletonObjects(也没有),尝试三级缓存singletonFactories,因为A经过ObjectFactory将本身提早曝光了,因此B可以经过ObjectFactory.getObject拿到A对象(半成品),B拿到A对象后顺利完成了初始化阶段一、二、三,彻底初始化以后将本身放入到一级缓存singletonObjects中。此时返回A中,A此时能拿到B的对象顺利完成本身的初始化阶段二、三,最终A也完成了初始化,进去了一级缓存singletonObjects中,并且更加幸运的是,因为B拿到了A的对象引用,因此B如今hold住的A对象完成了初始化。

Spring为何不能解决非单例属性之外的循环依赖?

通过以下几个问题,辅助我们进一步理解。

Spring为什么不能解决构造器的循环依赖?

构造器注入形成的循环依赖: 也就是beanB需要在beanA的构造函数中完成初始化,beanA也需要在beanB的构造函数中完成初始化,这种情况的结果就是两个bean都不能完成初始化,循环依赖难以解决。

Spring解决循环依赖主要是依赖三级缓存,但是的在调用构造方法之前还未将其放入三级缓存之中,因此后续的依赖调用构造方法的时候并不能从三级缓存中获取到依赖的Bean,因此不能解决。

Spring为什么不能解决prototype作用域循环依赖?

这种循环依赖同样无法解决,因为spring不会缓存‘prototype’作用域的bean,而spring中循环依赖的解决正是通过缓存来实现的。

Spring为什么不能解决多例的循环依赖?

多实例Bean是每次调用一次getBean都会执行一次构造方法并且给属性赋值,根本没有三级缓存,因此不能解决循环依赖。

那么其它循环依赖如何解决?

那么实际开发中,类似的依赖是如何解决?

  • 生成代理对象产生的循环依赖

这类循环依赖问题解决方法很多,主要有:

  1. 使用@Lazy注解,延迟加载
  2. 使用@DependsOn注解,指定加载先后关系
  3. 修改文件名称,改变循环依赖类的加载顺序
  • 使用@DependsOn产生的循环依赖

这类循环依赖问题要找到@DependsOn注解循环依赖的地方,迫使它不循环依赖就可以解决问题。

  • 多例循环依赖

这类循环依赖问题可以通过把bean改成单例的解决。

  • 构造器循环依赖

这类循环依赖问题可以通过使用@Lazy注解解决。

重点:Spring中Bean的生命周期

Spring 只帮我们管理单例模式 Bean 的完整生命周期,对于 prototype 的 bean ,Spring 在创建好交给使用者之后则不会再管理后续的生命周期。

Spring 容器可以管理 singleton 作用域 Bean 的生命周期,在此作用域下,Spring 能够精确地知道该 Bean 何时被创建,何时初始化完成,以及何时被销毁。

而对于 prototype 作用域的 Bean,Spring 只负责创建,当容器创建了 Bean 的实例后,Bean 的实例就交给客户端代码管理,Spring 容器将不再跟踪其生命周期。每次客户端请求 prototype 作用域的 Bean 时,Spring 容器都会创建一个新的实例,并且不会管那些被配置成 prototype 作用域的 Bean 的生命周期。

了解 Spring 生命周期的意义就在于,可以利用 Bean 在其存活期间的指定时刻完成一些相关操作。这种时刻可能有很多,但一般情况下,会在 Bean 被初始化后和被销毁前执行一些相关操作。

Spring Bean生命周期流程

在 Spring 中,Bean 的生命周期是一个很复杂的执行过程,我们可以利用 Spring 提供的方法定制 Bean 的创建过程。

Spring 容器中 Bean 的生命周期流程

cfcf56d58ec10344dae621b88f186628 - Spring框架系列(8) - Spring IOC实现原理详解之Bean实例化(生命周期,循环依赖等)

  • 如果 BeanFactoryPostProcessor 和 Bean 关联, 则调用postProcessBeanFactory方法.(即首先尝试从Bean工厂中获取Bean)
  • 如果 InstantiationAwareBeanPostProcessor 和 Bean 关联,则调用postProcessBeforeInstantiation方法
  • 根据配置情况调用 Bean 构造方法实例化 Bean
  • 利用依赖注入完成 Bean 中所有属性值的配置注入
  • 如果 InstantiationAwareBeanPostProcessor 和 Bean 关联,则调用postProcessAfterInstantiation方法和postProcessProperties
  • 调用xxxAware接口 (上图只是给了几个例子)
    • 第一类Aware接口
      • 如果 Bean 实现了 BeanNameAware 接口,则 Spring 调用 Bean 的 setBeanName() 方法传入当前 Bean 的 id 值。
      • 如果 Bean 实现了 BeanClassLoaderAware 接口,则 Spring 调用 setBeanClassLoader() 方法传入classLoader的引用。
      • 如果 Bean 实现了 BeanFactoryAware 接口,则 Spring 调用 setBeanFactory() 方法传入当前工厂实例的引用。
    • 第二类Aware接口
      • 如果 Bean 实现了 EnvironmentAware 接口,则 Spring 调用 setEnvironment() 方法传入当前 Environment 实例的引用。
      • 如果 Bean 实现了 EmbeddedValueResolverAware 接口,则 Spring 调用 setEmbeddedValueResolver() 方法传入当前 StringValueResolver 实例的引用。
      • 如果 Bean 实现了 ApplicationContextAware 接口,则 Spring 调用 setApplicationContext() 方法传入当前 ApplicationContext 实例的引用。
      • ...
  • 如果 BeanPostProcessor 和 Bean 关联,则 Spring 将调用该接口的预初始化方法 postProcessBeforeInitialzation() 对 Bean 进行加工操作,此处非常重要,Spring 的 AOP 就是利用它实现的。
  • 如果 Bean 实现了 InitializingBean 接口,则 Spring 将调用 afterPropertiesSet() 方法。(或者有执行@PostConstruct注解的方法)
  • 如果在配置文件中通过 init-method 属性指定了初始化方法,则调用该初始化方法。
  • 如果 BeanPostProcessor 和 Bean 关联,则 Spring 将调用该接口的初始化方法 postProcessAfterInitialization()。此时,Bean 已经可以被应用系统使用了。
  • 如果在 中指定了该 Bean 的作用范围为 scope="singleton",则将该 Bean 放入 Spring IoC 的缓存池中,将触发 Spring 对该 Bean 的生命周期管理;如果在 中指定了该 Bean 的作用范围为 scope="prototype",则将该 Bean 交给调用者,调用者管理该 Bean 的生命周期,Spring 不再管理该 Bean。
  • 如果 Bean 实现了 DisposableBean 接口,则 Spring 会调用 destory() 方法将 Spring 中的 Bean 销毁;(或者有执行@PreDestroy注解的方法)
  • 如果在配置文件中通过 destory-method 属性指定了 Bean 的销毁方法,则 Spring 将调用该方法对 Bean 进行销毁。

Bean的完整生命周期经历了各种方法调用,这些方法可以划分为以下几类:(结合上图,需要有如下顶层思维)

  • Bean自身的方法: 这个包括了Bean本身调用的方法和通过配置文件中的init-method和destroy-method指定的方法
  • Bean级生命周期接口方法: 这个包括了BeanNameAware、BeanFactoryAware、ApplicationContextAware;当然也包括InitializingBean和DiposableBean这些接口的方法(可以被@PostConstruct和@PreDestroy注解替代)
  • 容器级生命周期接口方法: 这个包括了InstantiationAwareBeanPostProcessor 和 BeanPostProcessor 这两个接口实现,一般称它们的实现类为“后处理器”。
  • 工厂后处理器接口方法: 这个包括了AspectJWeavingEnabler, ConfigurationClassPostProcessor, CustomAutowireConfigurer等等非常有用的工厂后处理器接口的方法。工厂后处理器也是容器级的。在应用上下文装配配置文件之后立即调用。

Spring Bean生命周期案例

我们通过一个例子来验证上面的整个流程

定义Bean(这里是User), 并让它实现BeanNameAware,BeanFactoryAware,ApplicationContextAware接口和InitializingBean,DisposableBean接口:

package tech.pdai.springframework.entity;

import lombok.ToString;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.BeanFactoryAware;
import org.springframework.beans.factory.BeanNameAware;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;

/**
 * @author pdai
 */
@Slf4j
@ToString
public class User implements BeanFactoryAware, BeanNameAware, ApplicationContextAware,
        InitializingBean, DisposableBean {
    /**
 * user's name.
 */
    private String name;

    /**
 * user's age.
 */
    private int age;

    /**
 * bean factory.
 */
    private BeanFactory beanFactory;

    /**
 * application context.
 */
    private ApplicationContext applicationContext;

    /**
 * bean name.
 */
    private String beanName;

    public User() {
        log.info("execute User#new User()");
    }

    public void setName(String name) {
        log.info("execute User#setName({})", name);
        this.name = name;
    }

    public void setAge(int age) {
        log.info("execute User#setAge({})", age);
        this.age = age;
    }

    @Override
    public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
        log.info("execute BeanFactoryAware#setBeanFactory");
        this.beanFactory = beanFactory;
    }

    @Override
    public void setBeanName(String s) {
        log.info("execute BeanNameAware#setBeanName");
        this.beanName = s;
    }

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        log.info("execute ApplicationContextAware#setApplicationContext");
        this.applicationContext = applicationContext;
    }

    @Override
    public void destroy() throws Exception {
        log.info("execute DisposableBean#destroy");
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        log.info("execute InitializingBean#afterPropertiesSet");
    }

    public void doInit() {
        log.info("execute User#doInit");
    }

    public void doDestroy() {
        log.info("execute User#doDestroy");
    }

}
折叠 

定义BeanFactoryPostProcessor的实现类

/**
 * @author pdai
 */
@Slf4j
@Component
public class MyBeanFactoryPostProcessor implements BeanFactoryPostProcessor {

    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory configurableListableBeanFactory) throws BeansException {
        log.info("execute BeanFactoryPostProcessor#postProcessBeanFactory");
    }
}

定义InstantiationAwareBeanPostProcessor的实现类

/**
 * @author pdai
 */
@Slf4j
@Component
public class MyInstantiationAwareBeanPostProcessor implements InstantiationAwareBeanPostProcessor {
    @Override
    public Object postProcessBeforeInstantiation(Class beanClass, String beanName) throws BeansException {
        log.info("execute InstantiationAwareBeanPostProcessor#postProcessBeforeInstantiation for {}", beanName);
        return InstantiationAwareBeanPostProcessor.super.postProcessBeforeInstantiation(beanClass, beanName);
    }

    @Override
    public boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {
        log.info("execute InstantiationAwareBeanPostProcessor#postProcessAfterInstantiation for {}", beanName);
        return InstantiationAwareBeanPostProcessor.super.postProcessAfterInstantiation(bean, beanName);
    }

    @Override
    public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) throws BeansException {
        log.info("execute InstantiationAwareBeanPostProcessor#postProcessProperties for {}", beanName);
        return InstantiationAwareBeanPostProcessor.super.postProcessProperties(pvs, bean, beanName);
    }
}

定义BeanPostProcessor的实现类

/**
 * @author pdai
 */
@Slf4j
@Component
public class MyBeanPostProcessor implements BeanPostProcessor {

    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        log.info("execute BeanPostProcessor#postProcessBeforeInitialization for {}", beanName);
        return BeanPostProcessor.super.postProcessBeforeInitialization(bean, beanName);
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        log.info("execute BeanPostProcessor#postProcessAfterInitialization for {}", beanName);
        return BeanPostProcessor.super.postProcessAfterInitialization(bean, beanName);
    }
}

通过Java配置方式初始化Bean

/**
 * @author pdai
 */
@Configuration
public class BeansConfig {

    @Bean(name = "user", initMethod = "doInit", destroyMethod = "doDestroy")
    public User create() {
        User user = new User();
        user.setName("pdai");
        user.setAge(18);
        return user;
    }
}

测试的主方法

/**
 * Cglib proxy demo.
 *
 * @author pdai
 */
@Slf4j
public class App {

    /**
 * main interface.
 *
 * @param args args
 */
    public static void main(String[] args) {
        log.info("Init application context");
        // create and configure beans
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(
                "tech.pdai.springframework");

        // retrieve configured instance
        User user = (User) context.getBean("user");

        // print info from beans
        log.info(user.toString());

        log.info("Shutdown application context");
        context.registerShutdownHook();
    }
}

输出结果(剔除无关输出):

12:44:42.547 [main] INFO tech.pdai.springframework.App - Init application context
...
12:44:43.134 [main] INFO tech.pdai.springframework.processor.MyBeanFactoryPostProcessor - execute BeanFactoryPostProcessor#postProcessBeanFactory
...
12:44:43.216 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'user'
12:44:43.216 [main] INFO tech.pdai.springframework.processor.MyInstantiationAwareBeanPostProcessor - execute InstantiationAwareBeanPostProcessor#postProcessBeforeInstantiation for user
12:44:43.236 [main] INFO tech.pdai.springframework.entity.User - execute User#new User()
12:44:43.237 [main] INFO tech.pdai.springframework.entity.User - execute User#setName(pdai)
12:44:43.237 [main] INFO tech.pdai.springframework.entity.User - execute User#setAge(18)
12:44:43.237 [main] INFO tech.pdai.springframework.processor.MyInstantiationAwareBeanPostProcessor - execute InstantiationAwareBeanPostProcessor#postProcessAfterInstantiation for user
12:44:43.237 [main] INFO tech.pdai.springframework.processor.MyInstantiationAwareBeanPostProcessor - execute InstantiationAwareBeanPostProcessor#postProcessProperties for user
12:44:43.242 [main] INFO tech.pdai.springframework.entity.User - execute BeanNameAware#setBeanName
12:44:43.242 [main] INFO tech.pdai.springframework.entity.User - execute BeanFactoryAware#setBeanFactory
12:44:43.242 [main] INFO tech.pdai.springframework.entity.User - execute ApplicationContextAware#setApplicationContext
12:44:43.242 [main] INFO tech.pdai.springframework.processor.MyBeanPostProcessor - execute BeanPostProcessor#postProcessBeforeInitialization for user
12:44:43.242 [main] INFO tech.pdai.springframework.entity.User - execute InitializingBean#afterPropertiesSet
12:44:43.243 [main] INFO tech.pdai.springframework.entity.User - execute User#doInit
12:44:43.243 [main] INFO tech.pdai.springframework.processor.MyBeanPostProcessor - execute BeanPostProcessor#postProcessAfterInitialization for user
12:44:43.270 [main] INFO tech.pdai.springframework.App - User(name=pdai, age=18)
12:44:43.270 [main] INFO tech.pdai.springframework.App - Shutdown application context
12:44:43.276 [SpringContextShutdownHook] INFO tech.pdai.springframework.entity.User - execute DisposableBean#destroy
12:44:43.276 [SpringContextShutdownHook] INFO tech.pdai.springframework.entity.User - execute User#doDestroy

参考文章

https://juejin.cn/post/6844903843596107790

https://www.zhihu.com/question/438247718/answer/1730527725

更多文章

首先, 从Spring框架的整体架构和组成对整体框架有个认知。

  • Spring基础 - Spring和Spring框架组成
    • Spring是什么?它是怎么诞生的?有哪些主要的组件和核心功能呢? 本文通过这几个问题帮助你构筑Spring和Spring Framework的整体认知。

其次,通过案例引出Spring的核心(IoC和AOP),同时对IoC和AOP进行案例使用分析。

基于Spring框架和IOC,AOP的基础,为构建上层web应用,需要进一步学习SpringMVC。

  • Spring基础 - SpringMVC请求流程和案例
    • 前文我们介绍了Spring框架和Spring框架中最为重要的两个技术点(IOC和AOP),那我们如何更好的构建上层的应用呢(比如web 应用),这便是SpringMVC;Spring MVC是Spring在Spring Container Core和AOP等技术基础上,遵循上述Web MVC的规范推出的web开发框架,目的是为了简化Java栈的web开发。 本文主要介绍SpringMVC的请求流程和基础案例的编写和运行。

Spring进阶 - IoC,AOP以及SpringMVC的源码分析

  • Spring进阶 - Spring IOC实现原理详解之IOC体系结构设计
    • 在对IoC有了初步的认知后,我们开始对IOC的实现原理进行深入理解。本文将帮助你站在设计者的角度去看IOC最顶层的结构设计
  • Spring进阶 - Spring IOC实现原理详解之IOC初始化流程
    • 上文,我们看了IOC设计要点和设计结构;紧接着这篇,我们可以看下源码的实现了:Spring如何实现将资源配置(以xml配置为例)通过加载,解析,生成BeanDefination并注册到IoC容器中的
  • Spring进阶 - Spring IOC实现原理详解之Bean实例化(生命周期,循环依赖等)
    • 上文,我们看了IOC设计要点和设计结构;以及Spring如何实现将资源配置(以xml配置为例)通过加载,解析,生成BeanDefination并注册到IoC容器中的;容器中存放的是Bean的定义即BeanDefinition放到beanDefinitionMap中,本质上是一个ConcurrentHashMap;并且BeanDefinition接口中包含了这个类的Class信息以及是否是单例等。那么如何从BeanDefinition中实例化Bean对象呢,这是本文主要研究的内容?
  • Spring进阶 - Spring AOP实现原理详解之切面实现
    • 前文,我们分析了Spring IOC的初始化过程和Bean的生命周期等,而Spring AOP也是基于IOC的Bean加载来实现的。本文主要介绍Spring AOP原理解析的切面实现过程(将切面类的所有切面方法根据使用的注解生成对应Advice,并将Advice连同切入点匹配器和切面类等信息一并封装到Advisor,为后续交给代理增强实现做准备的过程)。
  • Spring进阶 - Spring AOP实现原理详解之AOP代理
    • 上文我们介绍了Spring AOP原理解析的切面实现过程(将切面类的所有切面方法根据使用的注解生成对应Advice,并将Advice连同切入点匹配器和切面类等信息一并封装到Advisor)。本文在此基础上继续介绍,代理(cglib代理和JDK代理)的实现过程。
  • Spring进阶 - Spring AOP实现原理详解之Cglib代理实现
    • 我们在前文中已经介绍了SpringAOP的切面实现和创建动态代理的过程,那么动态代理是如何工作的呢?本文主要介绍Cglib动态代理的案例和SpringAOP实现的原理。
  • Spring进阶 - Spring AOP实现原理详解之JDK代理实现
    • 上文我们学习了SpringAOP Cglib动态代理的实现,本文主要是SpringAOP JDK动态代理的案例和实现部分。
  • Spring进阶 - SpringMVC实现原理之DispatcherServlet初始化的过程
    • 前文我们有了IOC的源码基础以及SpringMVC的基础,我们便可以进一步深入理解SpringMVC主要实现原理,包含DispatcherServlet的初始化过程和DispatcherServlet处理请求的过程的源码解析。本文是第一篇:DispatcherServlet的初始化过程的源码解析。
  • Spring进阶 - SpringMVC实现原理之DispatcherServlet处理请求的过程
    • 前文我们有了IOC的源码基础以及SpringMVC的基础,我们便可以进一步深入理解SpringMVC主要实现原理,包含DispatcherServlet的初始化过程和DispatcherServlet处理请求的过程的源码解析。本文是第二篇:DispatcherServlet处理请求的过程的源码解析。

转载请注明:xuhss » Spring框架系列(8) – Spring IOC实现原理详解之Bean实例化(生命周期,循环依赖等)

喜欢 (0)

您必须 登录 才能发表评论!