茅塞顿开: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的方法,我们再往里面看一下这个方法里面究竟有什么。可以发现给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进来了。
public Object postProcessBeforeInitialization(final Object bean, String beanName) throws BeansException {AccessControlContext acc = null;if (System.getSecurityManager() != null &&(bean instanceof EnvironmentAware || bean instanceof EmbeddedValueResolverAware ||bean instanceof ResourceLoaderAware || bean instanceof ApplicationEventPublisherAware ||bean instanceof MessageSourceAware || bean instanceof ApplicationContextAware)) {acc = this.applicationContext.getBeanFactory().getAccessControlContext();}if (acc != null) {AccessController.doPrivileged((PrivilegedAction
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
上面是跟着源码走了一遍。我看完之后的理解就是。Spring在整个设计上对于这种松耦合和可插拔真是做了非常多的工作。可以说Spring 本身的ioc的代码并不复杂。大量的代码工作都是为了方便开发者自己去拓展Spring的边界。让开发者可以更好的去控制和管理bean这个对象。Spring的代码建议多读几遍。虽然每一遍读起来都很痛苦。但是每一次读都会有新的感受。
本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!
