Aware接口
在整个Bean的生命周期的初始化阶段,有一个很重要的步骤就是执行相关的Aware接口,而整个Aware接口执行又可以分为两个阶段:
- 第一阶段,执行BeanXXXAware接口
- 执行其它Aware接口
至于为什么需要这样分,我们在进行源码分析的时候就明白了
我们可以发现,所有的Aware接口都是为了能让我们拿到容器中相关的资源,比如BeanNameAware,可以让我们拿到Bean的名称,ApplicationContextAware 可以让我们拿到整个容器。但是使用Aware接口也会相应的带来一些弊病,当我们去实现这些接口时,意味着我们的应用程序跟Spring容器发生了强耦合,违背了IOC的原则。所以一般情况下,并不推荐采用这种方式,除非我们在编写一些整个应用基础的组件。
Spring内部提供了如下这些Aware接口
初始化过程源码分析
回顾我们之前的流程图,我们可以看到,创建Bean的动作主要发生在3-11-6-4步骤中,主要分为三步:
- createBeanInstance ,创建实例
- populateBean,属性注入
- initializeBean,初始化
我们今天要分析的代码主要就是第3-11-6-4-3步,其完成的功能主要就是初始化,相对于我们之前分析过的代码来说,这段代码算比较简单的:
protected Object initializeBean(final String beanName, final Object bean, @Nullable RootBeanDefinition mbd) { if (System.getSecurityManager() != null) { AccessController.doPrivileged((PrivilegedAction<Object>) () -> { invokeAwareMethods(beanName, bean); return null; }, getAccessControlContext()); } else { // 第一步:执行aware接口中的方法,需要主要的是,不是所有的Aware接口都是在这步执行了 invokeAwareMethods(beanName, bean); } Object wrappedBean = bean; if (mbd == null || !mbd.isSynthetic()) { // 第二步:完成Aware接口方法的执行,以及@PostConstructor,@PreDestroy注解的处理 wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName); } try { // 第三步:完成初始化方法执行 invokeInitMethods(beanName, wrappedBean, mbd); } catch (Throwable ex) { throw new BeanCreationException( (mbd != null ? mbd.getResourceDescription() : null), beanName, "Invocation of init method failed", ex); } if (mbd == null || !mbd.isSynthetic()) { // 第四步:完成AOP代理 wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName); } return wrappedBean; }
第一步:执行部分aware接口中的方法
private void invokeAwareMethods(final String beanName, final Object bean) { if (bean instanceof Aware) { if (bean instanceof BeanNameAware) { ((BeanNameAware) bean).setBeanName(beanName); } if (bean instanceof BeanClassLoaderAware) { ClassLoader bcl = getBeanClassLoader(); if (bcl != null) { ((BeanClassLoaderAware) bean).setBeanClassLoader(bcl); } } if (bean instanceof BeanFactoryAware) { ((BeanFactoryAware) bean).setBeanFactory(AbstractAutowireCapableBeanFactory.this); } } }
可以看到,在invokeAwareMethods这个方法中,并不是所有的Aware接口都会被执行,只有BeanNameAware,BeanClassLoaderAware,BeanFactoryAware这三个接口会被执行,这也是为什么我单独将BeanXXXAware这一类的接口划分为一组的原因。这三个Aware接口分别实现的功能为:
BeanNameAware:获取Bean的名字
BeanClassLoaderAware:获取加载这个Bean的类加载器
BeanFactoryAware:获取当前的BeanFactory
第二步:完成Aware接口方法的执行,以及@PostConstructor,@PreDestroy注解的处理
- Aware接口执行,出了我们上面介绍的三个Aware接口,其余的接口都会在这个阶段执行,例如我们之前说到的ApplicationContextAware 接口,它会被一个专门的后置处理器ApplicationContextAwareProcessor处理。其余的接口也是类似的操作,这里就不在赘述了
- @PostConstructor,@PreDestroy两个注解的处理。这两个注解会被CommonAnnotationBeanPostProcessor这个后置处理器处理,需要注意的是@Resource注解也是被这个后置处理器进行处理的。关于注解的处理逻辑,我们后面的源码阅读相关文章中再做详细分析。
第三步:完成初始化方法执行
protected void invokeInitMethods(String beanName, final Object bean, @Nullable RootBeanDefinition mbd) throws Throwable { // 是否实现了 InitializingBean接口 boolean isInitializingBean = (bean instanceof InitializingBean); if (isInitializingBean && (mbd == null || // 这个判断基本恒成立,除非手动改变了BD的属性 !mbd.isExternallyManagedInitMethod("afterPropertiesSet"))) { if (logger.isTraceEnabled()) { logger.trace("Invoking afterPropertiesSet() on bean with name '" + beanName + "'"); } if (System.getSecurityManager() != null) { try { AccessController.doPrivileged((PrivilegedExceptionAction<Object>) () -> { // 调用afterPropertiesSet方法 ((InitializingBean) bean).afterPropertiesSet(); return null; }, getAccessControlContext()); } catch (PrivilegedActionException pae) { throw pae.getException(); } } else { // 调用afterPropertiesSet方法 ((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)) { invokeCustomInitMethod(beanName, bean, mbd); } } }
整段代码的逻辑还是很简单的,先判断是否实现了对应的生命周期回调的接口(InitializingBean),如果实现了接口,先调用接口中的afterPropertiesSet方法。之后在判断是否提供了initMethod,也就是在XML中的Bean标签中提供了init-method属性。
第四步:完成AOP代理
AOP代理实现的具体过程放到之后的文章中分析,我们暂时只需要知道AOP是在Bean完成了所有初始化方法后完成的即可。这也不难理解,在进行AOP之前必须保证我们的Bean已经被充分的”装配“了。
总结
就目前而言,我们可以将整个Bean的生命周期总结如下:
在上图中,实例话跟属性注入的过程我们还没有分析,在后续的文章中,我们将对其进行详细的分析。销毁阶段并不复杂,所以这里也不做分析了,直接给出结论,大概可以自己阅读代码,入口在容器的close方法中。
另外,我这里并没有将实现了LifeCycle接口的Bean中的start方法跟stop方法算入到整个Bean的生命周期中,大家只要知道,如果实现了SmartLifeCyle接口,那么在容器启动时也会默认调用其start方法,并且调用的时机在Bean完成初始化后,而stop方法将在Bean销毁前调用。