【Spring IOC】【六】容器源码解析- initializeBean剩下的初始化工作
1 前言
我们的bean经过的应该就剩下initializeBean这个方法,这个方法对上一步的populateBean属性填充完,做最后的剩余工作,这个里边的东西相比之前几个那可真是让人看着开心加愉快了,我们来看。
2 源码分析
2.1 方法通读
看一下 initializeBean 方法的源码:
protected Object initializeBean(String beanName, Object bean, @Nullable RootBeanDefinition mbd) { if (System.getSecurityManager() != null) { AccessController.doPrivileged((PrivilegedAction<Object>) () -> { invokeAwareMethods(beanName, bean); return null; }, getAccessControlContext()); } else { // aware后缀结尾的类大家应该很熟悉吧 // 若 bean 实现了 BeanNameAware、BeanFactoryAware、BeanClassLoaderAware 等接口,则向 bean 中注入相关对象 invokeAwareMethods(beanName, bean); } Object wrappedBean = bean; if (mbd == null || !mbd.isSynthetic()) { // 执行 bean 初始化前置操作 wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName); } try { /* * 调用初始化方法: * 1. 若 bean 实现了 InitializingBean 接口,则调用 afterPropertiesSet 方法 * 2. 若用户配置了 bean 的 init-method 属性,则调用用户在配置中指定的方法 */ 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()) { // 执行 bean 初始化后置操作,AOP 会在此处向目标对象中织入切面逻辑 wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName); } return wrappedBean; }
以上就是 initializeBean 方法的逻辑。该方法做了如下几件事情:
- 检测 bean 是否实现了 *Aware 类型接口,若实现,则向 bean 中注入相应的对象
- 执行 bean 初始化前置操作
- 执行初始化操作
- 执行 bean 初始化后置操作
2.2 invokeAwareMethods
根据 bean 所实现的 Aware 的类型,向 bean 中注入不同类型的对象。
private void invokeAwareMethods(String beanName, 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); } } }
2.3 invokeInitMethods
做了两件事,1、就是你的bean如果实现了InitializingBean,会调用你的afterPropertiesSet方法做你的东西。 2、执行你bean的init-method方法。
init-method可以配在xml也可以用注解像这样:@Bean(initMethod = "init", destroyMethod = "destroy")
protected void invokeInitMethods(String beanName, Object bean, @Nullable RootBeanDefinition mbd) throws Throwable { boolean isInitializingBean = (bean instanceof InitializingBean); if (isInitializingBean && (mbd == null || !mbd.hasAnyExternallyManagedInitMethod("afterPropertiesSet"))) { if (logger.isTraceEnabled()) { logger.trace("Invoking afterPropertiesSet() on bean with name '" + beanName + "'"); } if (System.getSecurityManager() != null) { try { AccessController.doPrivileged((PrivilegedExceptionAction<Object>) () -> { ((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.hasAnyExternallyManagedInitMethod(initMethodName)) { // 调用用户自定义的方法 invokeCustomInitMethod(beanName, bean, mbd); } } }
3 小结
这个方法还是比较舒服的,不会拖家带口的带出来一堆东西,Spring很多地方都给我们留了扩展,Spring就是给我们管理bean、增强bean的,管理也就是管理bean的生命周期,增强就是在创建的过程中,创建对应的代理对象出来。我们看完IOC 对于bean的几个创建过程中的方法也是有了大概的认识 比如getBean、doGetBean、createBean、doCreateBean、createBeanInstance、populateBean、intializeBean,中间涉及的缓存、代理、依赖解析、属性解析等等,好多细节也是还没太明白,还是要多看,多运用到自己的业务代码中去,哪里有理解不对的还望指正,今天就到这里了。