手撕spring bean的生命周期

 Springbean的生命周期一直是面试高频题,想答好,还得看源码

bean的生命周期,从源码角度来说,值得我们关注的主要有四个大点,穿插在bean的创建过程中,所以显得散乱:

实例化对应构造方法,

属性赋值对应setter方法的注入,

初始化和销毁是用户能自定义扩展的两个阶段,如我们可以指定初始化方法和销毁方法,这部分之前的文章有分析过。

对应的执行顺序为:

实例化->属性赋值->初始化->销毁

我们先来看实例化:

这里简单的提下注入bean的几种方式:

XML配置的方式:

1.构造器的方式:通过默认构造器创建 空构造方法必须存在 否则创建失败

<!--通过默认的无参构造函数创建-->
    <bean id="car1" class="com.cjian.bean.Car"/>

2.静态工厂方式:我们指定Spring使用静态工厂方法来创建Bean实例时,Spring将先解析配置文件,并根据配置文件指定的信息,**通过反射调用静态工厂类的静态工厂方法,并将该静态工厂方法的返回值作为Bean实例,在这个过程中,Spring不再负责创建Bean实例,Bean实例是由用户提供的静态工厂方法提供的

<!--通过静态工厂创建-->
    <bean id="car2" class="com.cjian.beanfactory.BeanFactory" factory-method="getCar1"/>
public class BeanFactory {
    //静态工厂
    public static Car getCar1(){
        return new Car();
    }
}

3.实例化工厂方式

 <!--通过工厂实例创建-->
    <bean id="carBeanFactory" class="com.cjian.beanfactory.BeanFactory"/>
    <bean id="car3" factory-bean="carBeanFactory" factory-method="getCar2"/>
public class BeanFactory {
    public Car getCar2(){
        return new Car();
    }

}

4.通过FactoryBean:需要将该实例注入到容器中

    <!--通过FactoryBean-->
    <bean id="car4" class="com.cjian.beanfactory.CarFactoryBean"/>
package com.cjian.beanfactory;

import com.cjian.bean.Car;

import org.springframework.beans.factory.FactoryBean;

/**
 * @description:
 * @author: CJ
 * @time: 2021/1/7 15:19
 */
public class CarFactoryBean implements FactoryBean<Car> {

    @Override
    public Car getObject() throws Exception {
        return new Car();
    }

    @Override
    public Class<?> getObjectType() {
        return null;
    }

    @Override
    public boolean isSingleton() {
        return true;
    }
}

2.通过注解的方式:

注解的方式也有很多种:

@Bean  @Import  (直接导入bean,实现ImportSelector接口,并通过@Import导入 实现ImportBeanDefinitionRegistrar接口,并通过@Import导入)

接下来我们来看下实例化的具体过程:

不管是注解方式还是xml配置方式,ioc容器的初始化都是从调用refresh()方法开始:

 

abstractApplicationContext.refresh():

public AnnotationConfigApplicationContext(Class<?>... componentClasses) {
        this();
        this.register(componentClasses);
        this.refresh();
    }

 

beanFactory.preInstantiateSingletons();

public void refresh() throws BeansException, IllegalStateException {
        synchronized(this.startupShutdownMonitor) {
            this.prepareRefresh();
            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();
            }

        }
    }

 protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {
        if (beanFactory.containsBean("conversionService") && beanFactory.isTypeMatch("conversionService", ConversionService.class)) {
            beanFactory.setConversionService((ConversionService)beanFactory.getBean("conversionService", ConversionService.class));
        }

        if (!beanFactory.hasEmbeddedValueResolver()) {
            beanFactory.addEmbeddedValueResolver((strVal) -> {
                return this.getEnvironment().resolvePlaceholders(strVal);
            });
        }

        String[] weaverAwareNames = beanFactory.getBeanNamesForType(LoadTimeWeaverAware.class, false, false);
        String[] var3 = weaverAwareNames;
        int var4 = weaverAwareNames.length;

        for(int var5 = 0; var5 < var4; ++var5) {
            String weaverAwareName = var3[var5];
            this.getBean(weaverAwareName);
        }

        beanFactory.setTempClassLoader((ClassLoader)null);
        beanFactory.freezeConfiguration();
        beanFactory.preInstantiateSingletons();
    }

 

在这里面会调用到beanFactory的getBean()方法->doGetBean():

这里也开始了bean的创建:

请看源码:

protected <T> T doGetBean(String name, @Nullable Class<T> requiredType, @Nullable Object[] args, boolean typeCheckOnly) throws BeansException {
        //对 name 进行转换,获取真正的 beanName
        String beanName = this.transformedBeanName(name);
        //从缓存中获取 bean 的实例(已经注册过的单例bean 都保存在 singletonObjects 中)
        //这里还有循环依赖的知识点,以后再说
        Object sharedInstance = this.getSingleton(beanName);
        Object bean;
        if (sharedInstance != null && args == null) {
            //...

            bean = this.getObjectForBeanInstance(sharedInstance, name, beanName, (RootBeanDefinition)null);
        } else {
            //如果是多实例的且bean正在创建,直接抛异常,这也是循环依赖无法解决的问题
            if (this.isPrototypeCurrentlyInCreation(beanName)) {
                throw new BeanCurrentlyInCreationException(beanName);
            }
            // 1. 在 parentBeanFactory 中如果存在 beanName,则直接返回父容器里面的 bean
            BeanFactory parentBeanFactory = this.getParentBeanFactory();
            if (parentBeanFactory != null && !this.containsBeanDefinition(beanName)) {
                String nameToLookup = this.originalBeanName(name);
                if (parentBeanFactory instanceof AbstractBeanFactory) {
                    return ((AbstractBeanFactory)parentBeanFactory).doGetBean(nameToLookup, requiredType, args, typeCheckOnly);
                }

                if (args != null) {
                    return parentBeanFactory.getBean(nameToLookup, args);
                }

                if (requiredType != null) {
                    return parentBeanFactory.getBean(nameToLookup, requiredType);
                }

                return parentBeanFactory.getBean(nameToLookup);
            }

            if (!typeCheckOnly) {
                this.markBeanAsCreated(beanName);
            }

            try {
                RootBeanDefinition mbd = this.getMergedLocalBeanDefinition(beanName);
                this.checkMergedBeanDefinition(mbd, beanName, args);
                // 2. 初始化当前 bean 依赖的 bean
                String[] dependsOn = mbd.getDependsOn();
                String[] var11;
                if (dependsOn != null) {
                    var11 = dependsOn;
                    int var12 = dependsOn.length;

                    for(int var13 = 0; var13 < var12; ++var13) {
                        String dep = var11[var13];
                        if (this.isDependent(beanName, dep)) {
                            throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Circular depends-on relationship between '" + beanName + "' and '" + dep + "'");
                        }

                        this.registerDependentBean(dep, beanName);

                        try {
                            // getBean() 会再递归调用 doGetBean(),以确保所依赖的 bean 全部初始化
                            this.getBean(dep);
                        } catch (NoSuchBeanDefinitionException var24) {
                            throw new BeanCreationException(mbd.getResourceDescription(), beanName, "'" + beanName + "' depends on missing bean '" + dep + "'", var24);
                        }
                    }
                }
                
                if (mbd.isSingleton()) {
                // 3. 创建 单实例bean
                    sharedInstance = this.getSingleton(beanName, () -> {
                        try {
                            return this.createBean(beanName, mbd, args);
                        } catch (BeansException var5) {
                            this.destroySingleton(beanName);
                            throw var5;
                        }
                    });
                    //如果bean为 FactoryBean的话,则调用FactoryBean.getObject() 来创建 bean 实例
                    bean = this.getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
                } else if (mbd.isPrototype()) {
                    //多实例bean
                    var11 = null;

                    Object prototypeInstance;
                    try {
                        this.beforePrototypeCreation(beanName);
                        prototypeInstance = this.createBean(beanName, mbd, args);
                    } finally {
                        this.afterPrototypeCreation(beanName);
                    }

                    bean = this.getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
                } else {
                    // 其他 scope 类型的 bean
                    String scopeName = mbd.getScope();
                    if (!StringUtils.hasLength(scopeName)) {
                        throw new IllegalStateException("No scope name defined for bean ´" + beanName + "'");
                    }

                    Scope 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, () -> {
                            this.beforePrototypeCreation(beanName);

                            Object var4;
                            try {
                                var4 = this.createBean(beanName, mbd, args);
                            } finally {
                                this.afterPrototypeCreation(beanName);
                            }

                            return var4;
                        });
                        bean = this.getObjectForBeanInstance(scopedInstance, name, beanName, mbd);
                    } catch (IllegalStateException var23) {
                        throw new BeanCreationException(beanName, "Scope '" + scopeName + "' is not active for the current thread; consider defining a scoped proxy for this bean if you intend to refer to it from a singleton", var23);
                    }
                }
            } catch (BeansException var26) {
                this.cleanupAfterBeanCreationFailure(beanName);
                throw var26;
            }
        }

      //...
    }

再来看 createBean()

protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
        throws BeanCreationException {

    RootBeanDefinition mbdToUse = mbd;
    ......

    // Give BeanPostProcessors a chance to return a proxy instead of the target bean instance.
    // 在实例化之前返回一个代理对象,BeanPostProcessor 可以创建一个代理 bean 返回(AOP的功能)
    // 执行 InstantiationAwareBeanPostProcessor.postProcessBeforeInstantiation  -- bean 实例化前置处理
    // 执行 InstantiationAwareBeanPostProcessor.postProcessAfterInitialization  -- bean 初始化后置处理
    //重点--这里以后单独分析
    Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
    if (bean != null) {
        return bean;
    }

    // 创建 bean
    Object beanInstance = doCreateBean(beanName, mbdToUse, args);
    return beanInstance;
}

doCreateBean():

protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args) throws BeanCreationException {

    // Instantiate the bean.
    BeanWrapper instanceWrapper = null;

    if (instanceWrapper == null) {
        // 创建 bean 的实例:通过默认构造函数反射生成、通过配置的构造函数生成(构造方法注入)、通过 factoryMethod 生成
        // 最终会生成一个 BeanWrapper
        instanceWrapper = createBeanInstance(beanName, mbd, args);
    }
    final Object bean = instanceWrapper.getWrappedInstance();
    Class<?> beanType = instanceWrapper.getWrappedClass();

    // Allow post-processors to modify the merged bean definition.
    // 允许 post-processors 修改 bean 的定义
    synchronized (mbd.postProcessingLock) {
        if (!mbd.postProcessed) {
            // 执行 MergedBeanDefinitionPostProcessor.postProcessMergedBeanDefinition
            applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
            mbd.postProcessed = true;
        }
    }

    // Eagerly cache singletons to be able to resolve circular references
    // even when triggered by lifecycle interfaces like BeanFactoryAware.
    boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences && isSingletonCurrentlyInCreation(beanName));
    if (earlySingletonExposure) {
        // 解决循环依赖相关
        addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
    }

    // Initialize the bean instance.
    Object exposedObject = bean;
    try {
        // 填充 bean 属性,处理属性注入:@Value, @Autowired, @Resource 等
        populateBean(beanName, mbd, instanceWrapper);
        // 初始化 bean:执行 aware 方法 --> BeanPostProcessor.before --> afterPropertiesSet()-->初始化方法 --> BeanPostProcessor.after
        exposedObject = initializeBean(beanName, exposedObject, mbd);
    } catch (Throwable ex) {
        if (ex instanceof BeanCreationException && beanName.equals(((BeanCreationException) ex).getBeanName())) {
            throw (BeanCreationException) ex;
        }
        else {
            throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Initialization of bean failed", ex);
        }
    }

    ......

    return exposedObject;
}

 protected void invokeInitMethods(String beanName, Object bean, @Nullable RootBeanDefinition mbd) throws Throwable {
        boolean isInitializingBean = bean instanceof InitializingBean;
        if (isInitializingBean && (mbd == null || !mbd.isExternallyManagedInitMethod("afterPropertiesSet"))) {
            if (this.logger.isTraceEnabled()) {
                this.logger.trace("Invoking afterPropertiesSet() on bean with name '" + beanName + "'");
            }

            if (System.getSecurityManager() != null) {
                try {
                    AccessController.doPrivileged(() -> {
                        ((InitializingBean)bean).afterPropertiesSet();
                        return null;
                    }, this.getAccessControlContext());
                } catch (PrivilegedActionException var6) {
                    throw var6.getException();
                }
            } else {
                ((InitializingBean)bean).afterPropertiesSet();
            }
        }

        if (mbd != null && bean.getClass() != NullBean.class) {
            String initMethodName = mbd.getInitMethodName();
            if (StringUtils.hasLength(initMethodName) && (!isInitializingBean || !"afterPropertiesSet".equals(initMethodName)) && !mbd.isExternallyManagedInitMethod(initMethodName)) {
                this.invokeCustomInitMethod(beanName, bean, mbd);
            }
        }

    }

接着属性赋值

populateBean:处理属性注入:@Value, @Autowired, @Resource 等,具体的代码就不贴了

然后初始化

initializeBean:执行 aware 方法 --> BeanPostProcessor.applyBeanPostProcessorsBeforeInitialization-->  afterPropertiesSet()-->初始化方法(init-method)-->BeanPostProcessor.applyBeanPostProcessorsAfterInitialization

Aware ,英文翻译是意识到的,感知的,Spring 提供了诸多 **Aware 接口用于辅助 Spring Bean 以编程的方式调用 Spring 容器,通过实现这些接口,可以增强 Spring Bean 的功能。

Spring 提供了如下系列的 Aware 接口:

  • LoadTimeWeaverAware:加载Spring Bean时织入第三方模块,如AspectJ
  • BeanClassLoaderAware:加载Spring Bean的类加载器
  • BootstrapContextAware:资源适配器BootstrapContext,如JCA,CCI
  • ResourceLoaderAware:底层访问资源的加载器
  • BeanFactoryAware:声明BeanFactory
  • PortletConfigAware:PortletConfig
  • PortletContextAware:PortletContext
  • ServletConfigAware:ServletConfig
  • ServletContextAware:ServletContext
  • MessageSourceAware:国际化
  • ApplicationEventPublisherAware:应用事件
  • NotificationPublisherAware:JMX通知
  • BeanNameAware:声明Spring Bean的名字

比如BeanNameAware:

如果一个类实现了该接口,则可以获取自己的实例在ioc容器中的id(beanName),点击查看示例

BeanPostProcessor 的作用是:如果我们想要在 Spring 容器完成 Bean 的实例化,配置和其他的初始化后添加一些自己的逻辑处理,那么请使用该接口,这个接口给与了用户充足的权限去更改或者扩展 Spring,是我们对 Spring 进行扩展和增强处理一个必不可少的接口。

通过方法名称可知是在初始化之前和之后执行,再看下源码展现:

protected Object initializeBean(String beanName, Object bean, @Nullable RootBeanDefinition mbd) {
        if (System.getSecurityManager() != null) {
            AccessController.doPrivileged(() -> {
                this.invokeAwareMethods(beanName, bean);
                return null;
            }, this.getAccessControlContext());
        } else {
            //执行aware接口方法
            this.invokeAwareMethods(beanName, bean);
        }

        Object wrappedBean = bean;
        if (mbd == null || !mbd.isSynthetic()) {
            //执行bean的后置处理的before方法
            wrappedBean = this.applyBeanPostProcessorsBeforeInitialization(bean, beanName);
        }

        try {
            //执行自定义的初始化方法,如init-method,afterPropertiesSet等
            this.invokeInitMethods(beanName, wrappedBean, mbd);
        } catch (Throwable var6) {
            throw new BeanCreationException(mbd != null ? mbd.getResourceDescription() : null, beanName, "Invocation of init method failed", var6);
        }

        if (mbd == null || !mbd.isSynthetic()) {
            // //执行bean的后置处理的after方法
            wrappedBean = this.applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
        }

        return wrappedBean;
    }

初始化方法:初始化方法有一下几种:

1.指定init-method

2.实现InitializingBean

3.使用@PostConstruct注解(底层原理为BeanPostProcessor

或者使用上面的BeanPostProcessor

 

最后销毁

销毁一般在容器关闭的时候执行,销毁方法有以下几种:

1.指定destroyMethod

2.让Bean实现DisposableBean接口

3.使用@PreDestory注解(底层原理为BeanPostProcessor

 

来看下流程图:

bean的生命周期

 

 

 

Spring Bean对象的作用域(给某人看):

在Spring容器中管理的Bean对象,可以在声明时通过scope属性或者相关注解指定其作用域

在Spring容器中,Bean对象的作用域一共有5种:singleton(单例)、prototype(多实例)、request(HTTP请求)、session(会话)、global-session(全局会话)。

 

Bean的五种作用域

singlteon在ioc容器中仅存在一个Bean实例,容器一加载(初始化)就会去创建,也是默认值
prototypeioc容器加载的时候不创建,获取的时候才会创建,且每次都返回一个新的bean
request每次http请求都会创建一个新的bean
session同一个http session共享一个bean,不同session使用不同的bean
globalSession一般用于全局会话

其中最常用的是singleton和prototype两种:

1)singleton(单例模式)

singleton是默认的作用域,当我们定义Bean时,如果没有给scope指定属性值,Spring会默认Bean的作用域为singleton。singleton属于单例模式,被singleton标识的对象具备全局唯一性,也就是在整个spring的容器中有且仅有一个该Bean的实例。

singleton的 配置文件如下:

<!-- 通过指定scope属性的值,来确定Bean的作用域 -->
<bean id="user" class="com.beans.User" 
   scope="singleton">
</bean>

2)prototype:这个作用域标识的对象每次获取调用都会创建新的对象

<!-- 通过指定scope属性的值,来确定Bean的作用域 -->
<bean id="user" class="com.beans.User" 
    scope="prototype">
</bean>

至于request(HTTP请求)、session(会话)、global-session(全局会话)三种作用域,用的话一般会配合SpringMVC框架进行使用,在这里不做深入了解。

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值