spring源码解析之 25 bean的初始化 前面我们已经分析了bean的创建,属性的注入,依赖处理,其实这时bean基本上已经可以用了,不知道你还记不记得我们在xml中还可以配置init-method属性,这个到现在为止还没有处理,这就是最后一步初始化,也就是 initializeBean()
,所以这篇文章我们分析 doCreateBean()
中最后一步:初始化 bean。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 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 { invokeAwareMethods(beanName, bean); } Object wrappedBean = bean; if (mbd == null || !mbd.isSynthetic()) { wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName); } try { invokeInitMethods(beanName, wrappedBean, mbd); } catch (Throwable ex) { 。。。省略异常 } if (mbd == null || !mbd.isSynthetic()) { wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName); } return wrappedBean; }
初始化 bean 的方法其实就是三个步骤的处理,而这三个步骤主要还是根据用户设定的来进行初始化,这三个过程为:
激活 Aware 方法
后置处理器的应用
激活自定义的 init 方法
激活 Aware 方法
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的名字
invokeAwareMethods()
源码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 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 ); } } }
这里代码就没有什么好说的,主要是处理 BeanNameAware、BeanClassLoaderAware、BeanFactoryAware。关于 Aware 接口,后面会专门出篇文章对其进行详细分析说明的。
后置处理器的应用
BeanPostProcessor 在前面介绍 bean 加载的过程曾多次遇到,相信各位不陌生,这是 Spring 中开放式框架中必不可少的一个亮点。BeanPostProcessor 的作用是:如果我们想要在 Spring 容器完成 Bean 的实例化,配置和其他的初始化后添加一些自己的逻辑处理,那么请使用该接口,这个接口给与了用户充足的权限去更改或者扩展 Spring,是我们对 Spring 进行扩展和增强处理一个必不可少的接口。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 public Object applyBeanPostProcessorsBeforeInitialization (Object existingBean, String beanName) throws BeansException { Object result = existingBean; for (BeanPostProcessor beanProcessor : getBeanPostProcessors()) { Object current = beanProcessor.postProcessBeforeInitialization(result, beanName); if (current == null ) { return result; } result = current; } return result; } @Override public Object applyBeanPostProcessorsAfterInitialization (Object existingBean, String beanName) throws BeansException { Object result = existingBean; for (BeanPostProcessor beanProcessor : getBeanPostProcessors()) { Object current = beanProcessor.postProcessAfterInitialization(result, beanName); if (current == null ) { return result; } result = current; } return result; }
其实逻辑就是通过 getBeanPostProcessors()
获取定义的 BeanPostProcessor ,然后分别调用其 postProcessBeforeInitialization()
、postProcessAfterInitialization()
进行业务处理。
激活自定义的 init 方法
如果熟悉 <bean>
标签的配置,一定不会忘记 init-method
方法,该方法的执行就是在这里执行的。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 protected void invokeInitMethods (String beanName, final Object bean, @Nullable RootBeanDefinition mbd) throws Throwable { boolean isInitializingBean = (bean instanceof InitializingBean); if (isInitializingBean && (mbd == null || !mbd.isExternallyManagedInitMethod("afterPropertiesSet" ))) { if (logger.isDebugEnabled()) { } if (System.getSecurityManager() != null ) { try { AccessController.doPrivileged((PrivilegedExceptionAction<Object>) () -> {((InitializingBean) bean).afterPropertiesSet(); return null ; }, getAccessControlContext()); } catch (PrivilegedActionException pae) { throw pae.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)) { invokeCustomInitMethod(beanName, bean, mbd); } } }
首先检查是否为 InitializingBean ,如果是的话需要执行 afterPropertiesSet()
,因为我们除了可以使用 init-method
来自定初始化方法外,还可以实现 InitializingBean 接口,该接口仅有一个 afterPropertiesSet()
方法,而两者的执行先后顺序是先 afterPropertiesSet()
后 init-method
。
注册DisposableBean
spring中不但提供了对于初始化方法的扩展入口同样也提供了销毁方法的扩展入口,对于销毁方法的扩展,处理我们熟知的配置属性destroy-method方法外,用户还可以注册后处理器DestructionAwareBeanpostProcessor来统一处理bean的销毁方法,具体代码如下
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 protected void registerDisposableBeanIfNecessary (String beanName, Object bean, RootBeanDefinition mbd) { AccessControlContext acc = (System.getSecurityManager() != null ? getAccessControlContext() : null ); if (!mbd.isPrototype() && requiresDestruction(bean, mbd)) { if (mbd.isSingleton()) { registerDisposableBean(beanName, new DisposableBeanAdapter (bean, beanName, mbd, getBeanPostProcessors(), acc)); } else { Scope scope = this .scopes.get(mbd.getScope()); if (scope == null ) { } scope.registerDestructionCallback(beanName, new DisposableBeanAdapter (bean, beanName, mbd, getBeanPostProcessors(), acc)); } } }
其实这个销毁方法对于单例bean来说,扩展在这里我感觉是没有多大作用,因为单例bean的销毁是随着整个容器而销毁,而整个容器的销毁也代表者这个应用销毁,不起作用所以这里掉不掉用销毁方法已经没什么作用。对于其他的scope,是可以起作用的,类如request,session的scope是可以在里面加入一些定制化的逻辑。后面分析springMVC时会具体说道。