Spring容器里面 Bean的创建与Bean的生命周期

在工作或者学习中我们经常会使用spring的依赖注入来创建对象,并且将对象交给IOC容器去管理。那么spring究竟是如何为我们创建bean,以及是如何管理bean的呢?

bean的创建

我们可以看AbstractApplicationContext类中的refresh方法,spring在容器创建完成之后会调用refresh方法来初始化、刷新容器里面的bean:
这里我们把这个方法抠出来看看

	@Override
	public void refresh() throws BeansException, IllegalStateException {
		synchronized (this.startupShutdownMonitor) {
			// 为刷新过程准备上下文环境
			prepareRefresh();
			// 告诉子类刷新内部bean工厂
			ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
			// 准备bean工厂以在此上下文中使用
			prepareBeanFactory(beanFactory);
			try {
				// 为bean工厂添加后置处理器
				postProcessBeanFactory(beanFactory);
				// 执行bean工厂的后置处理器
				invokeBeanFactoryPostProcessors(beanFactory);
				// 为beanfactory里面的bean注册后置处理器
				registerBeanPostProcessors(beanFactory);
				// 初始化此上下文的消息源
				initMessageSource();
				// 初始化上下文事件广播
				initApplicationEventMulticaster();
				// 在特定的上下文子类中初始化其他特殊bean
				onRefresh();
				// 检查bean上面的监听器并且注册
				registerListeners();
				// 实例化所有(非懒加载)的单例
				finishBeanFactoryInitialization(beanFactory);
				// 最后,发布相应的事件
				finishRefresh();
			}
			catch (BeansException ex) {
				if (logger.isWarnEnabled()) {
					logger.warn("Exception encountered during context initialization - " +
							"cancelling refresh attempt: " + ex);
				}
				// 销毁已经创建的单例bean,避免浪费空间
				destroyBeans();
				// 重置'有效'标志
				cancelRefresh(ex);
				// Propagate exception to caller.
				throw ex;
			}
			finally {
				// Reset common introspection caches in Spring's core, since we
				// might not ever need metadata for singleton beans anymore...
				resetCommonCaches();
			}
		}
	}

在上面的代码中下面这个方法就是其中创建bean的关键方法
Spring容器里面 Bean的创建与Bean的生命周期
我们继续往下跟,这里会调用getBean方法
Spring容器里面 Bean的创建与Bean的生命周期
然后又会调用doGetBean 方法,在doGetBean方法里面我们找到这一段代码,就是创建bean实例的代码
Spring容器里面 Bean的创建与Bean的生命周期
这里面又会有一堆判断,然后调用doCreateBean,后面又会调用createBeanInstance 方法,这里createBeanInstance 方法就是真正的创建实例的方法,OK我们进入这个方法之后会看到他在返回的时候调用了instantiateBean这个方法
Spring容器里面 Bean的创建与Bean的生命周期
我们继续跟进去看

	/**
	 * Instantiate the given bean using its default constructor.
	 * @param beanName the name of the bean
	 * @param mbd the bean definition for the bean
	 * @return a BeanWrapper for the new instance
	 */
	protected BeanWrapper instantiateBean(final String beanName, final RootBeanDefinition mbd) {
		try {
			Object beanInstance;
			final BeanFactory parent = this;
			if (System.getSecurityManager() != null) {
				beanInstance = AccessController.doPrivileged((PrivilegedAction<Object>) () ->
						getInstantiationStrategy().instantiate(mbd, beanName, parent),
						getAccessControlContext());
			}
			else {
				beanInstance = getInstantiationStrategy().instantiate(mbd, beanName, parent);
			}
			BeanWrapper bw = new BeanWrapperImpl(beanInstance);
			initBeanWrapper(bw);
			return bw;
		}
		catch (Throwable ex) {
			throw new BeanCreationException(
					mbd.getResourceDescription(), beanName, "Instantiation of bean failed", ex);
		}
	}

上面代码中的instantiate方法就是创建bean的方法,并且点所生成的bean包装成了一个通用的BeanWrapper 类型, 我们看一下这个方法

@Override
	public Object instantiate(RootBeanDefinition bd, @Nullable String beanName, BeanFactory owner) {
		//如果没有覆盖,请不要使用CGLIB覆盖类。
		if (!bd.hasMethodOverrides()) {
			Constructor<?> constructorToUse;
			synchronized (bd.constructorArgumentLock) {
				constructorToUse = (Constructor<?>) bd.resolvedConstructorOrFactoryMethod;
				if (constructorToUse == null) {
					final Class<?> clazz = bd.getBeanClass();
					if (clazz.isInterface()) {
						throw new BeanInstantiationException(clazz, "Specified class is an interface");
					}
					try {
						if (System.getSecurityManager() != null) {
							constructorToUse = AccessController.doPrivileged(
									(PrivilegedExceptionAction<Constructor<?>>) clazz::getDeclaredConstructor);
						}
						else {
							constructorToUse = clazz.getDeclaredConstructor();
						}
						bd.resolvedConstructorOrFactoryMethod = constructorToUse;
					}
					catch (Throwable ex) {
						throw new BeanInstantiationException(clazz, "No default constructor found", ex);
					}
				}
			}
			return BeanUtils.instantiateClass(constructorToUse);
		}
		else {
			// 必须使用CGLIB代理生成实例
			return instantiateWithMethodInjection(bd, beanName, owner);
		}
	}

在这里我们可以看到,spring会判断类里面是否有重写的方法,如果有的话就会使用Cgilb 去生成对象,否则的话就直接用反射生成对象。

bean的生命周期

既然spring容器帮我们创建了容器,那么他也就能为我们销毁容器,那么就一定会有一个对应的声明周期。
在spring容器中bean的而生命周期为 创建–> 初始化–>销毁。同时spring也为我们提供了bean生命周期 的监控,一共有三种方式:使用@bean注解里面的属性 initMethod 和 destroyMethod ,让bean实现InitializingBean 和 DisposableBean接口;使用JSR250规范里面的注解 @PostConstruct: 在Bean创建完成,且属于赋值完成后进行初始化,属于JDK规范的注解,@PreDestroy: 在bean将被移除之前进行通知, 在容器销毁之前进行清理工作。

1、使用@bean注解里面的属性 initMethod 和 destroyMethod
我们在bean里面添加两个方法,初始化和销毁

Spring容器里面 Bean的创建与Bean的生命周期
我们在配置类里面为该bean加上如**解

@Configuration
public class PdfConfigration {
    @Bean(initMethod = "init",destroyMethod = "destroy")
    public ParseToPdf parseExcel(){
        return new ParseExcelToPdf();
    }

2、让bean实现InitializingBean 和 DisposableBean接口
实现接口之后会要求重写两个方法,其中afterPropertiesSet 为初始化方法,也就是在属性赋值之后执行这个方法。
Spring容器里面 Bean的创建与Bean的生命周期
3、使用@PostConstruct 和 @PreDestroy
Spring容器里面 Bean的创建与Bean的生命周期

这样通过以上三种方式我们都可以监控bean的生命周期,并且做一些我们想要做的事情。