javascript
茅塞顿开:Spring Aware原理解析
問題
為什么被Spring管理的類。只要實現了Aware接口。Spring就會自動把對應的對象注入進來。這個bean如果想要使用直接使用就可以了。如下: Spring會自動把ApplicationContext注入到AwareTest這個bean里面。
public class AwareTest implements ApplicationContextAware {public ApplicationContext applicationContext;@Overridepublic void setApplicationContext(ApplicationContext applicationContext) throws BeansException {this.applicationContext = applicationContext;}public void checkAware(){if(applicationContext != null){System.out.println("ApplicationContext inject success");}} }源碼解析:
1. 我們都知道在AbstractApplicationContext里面真正的啟動ApplicationContext的函數是refresh()方法。具體的方法如下
public void refresh() throws BeansException, IllegalStateException {synchronized (this.startupShutdownMonitor) {// Prepare this context for refreshing.prepareRefresh();// Tell the subclass to refresh the internal bean factory.ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();// Prepare the bean factory for use in this context.prepareBeanFactory(beanFactory);try {// Allows post-processing of the bean factory in context subclasses.postProcessBeanFactory(beanFactory);// Invoke factory processors registered as beans in the context.invokeBeanFactoryPostProcessors(beanFactory);// Register bean processors that intercept bean creation.registerBeanPostProcessors(beanFactory);// Initialize message source for this context.initMessageSource();// Initialize event multicaster for this context.initApplicationEventMulticaster();// Initialize other special beans in specific context subclasses.onRefresh();// Check for listener beans and register them.registerListeners();// Instantiate all remaining (non-lazy-init) singletons.finishBeanFactoryInitialization(beanFactory);// Last step: publish corresponding event.finishRefresh();}catch (BeansException ex) {if (logger.isWarnEnabled()) {logger.warn("Exception encountered during context initialization - " +"cancelling refresh attempt: " + ex);}// Destroy already created singletons to avoid dangling resources.destroyBeans();// Reset 'active' flag.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();}}}2. 可以看到有一個prepareBeanFactory的方法,我們再往里面看一下這個方法里面究竟有什么??梢园l現給BeanFactory添加了一個BeanPostProcessor。名字是ApplicationContextAwareProcessor?
protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) {// Tell the internal bean factory to use the context's class loader etc.beanFactory.setBeanClassLoader(getClassLoader());beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader()));beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment()));// Configure the bean factory with context callbacks.beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));beanFactory.ignoreDependencyInterface(EnvironmentAware.class);... 多余的代碼不貼出來了}3. BeanPostProcessor這個接口我們都很熟悉了。我們看一下這個里面PostProcessBeforeInitialization()函數。傳入bean和beanName。最后是調用了invokeAwareInterfaces(bean)這個函數。如果bean 是aware類的子類。那么就調用bean的set方法將ApplicationContext塞到bean里面。然后業務代碼在需要使用ApplicationContext的時候就可以直接使用了。因為已經被set進來了。
?
4. 我們再來看一下。Spring是什么時候調用了BeanPostProcessor的postProcessBeforeInitialization函數的。在AbstractAutowireCapableBeanFactory的initializeBean方法里面 , 在調用InvokeInitMethods的方法之前。先執行了applyBeanPost
ProcessorBeforeInitialization的方法。這個方法里面就是將所有的BeanPostProcessor的的postProcessBeforeInitialization()都執行一遍。包括之前創建的ApplicationContextAwareProcessor。于是ApplicationContextAwareProcessor這個時刻就將ApplicationContext注入到我們的Bean里面了。
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) {throw new BeanCreationException((mbd != null ? mbd.getResourceDescription() : null),beanName, "Invocation of init method failed", ex);}if (mbd == null || !mbd.isSynthetic()) {wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);}return wrappedBean;}上面是跟著源碼走了一遍。我看完之后的理解就是。Spring在整個設計上對于這種松耦合和可插拔真是做了非常多的工作??梢哉fSpring 本身的ioc的代碼并不復雜。大量的代碼工作都是為了方便開發者自己去拓展Spring的邊界。讓開發者可以更好的去控制和管理bean這個對象。Spring的代碼建議多讀幾遍。雖然每一遍讀起來都很痛苦。但是每一次讀都會有新的感受。
?
總結
以上是生活随笔為你收集整理的茅塞顿开:Spring Aware原理解析的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: SpringBoot2.x启动原理概述
- 下一篇: Spring源码版本命名规则及下载安装(