深入理解Spring IOC之扩展篇(四)、Aware接口

本篇讲的是Spring中的Aware接口,也应该是整个系列中最简单的一篇了,但是简单并不代表这玩意不重要,我们很多时候还是会用Aware接口去为我们做事情的。

我们知道,使用了Spring容器之后,我们创建对象这件事情完完全全的交给了Spring,在创建好了之后我们直接拿来用就可以了,容器内的东西对于我们的bean来说完全是透明的。为了让我们的bean可以感知到容器内的一些东西,所以Spring为我们提供了Aware接口,看过我之前文章的小伙伴肯定都知道,在初始化bean的时候有这么一段代码

private void invokeAwareMethods(final String beanName, final Object bean) {
		// 所谓的xxxAware,就是让这个bean和xxx产生关联
		if (bean instanceof Aware) {
			// 设置名称
			if (bean instanceof BeanNameAware) {
				((BeanNameAware) bean).setBeanName(beanName);
			}
			// 类加载器
			if (bean instanceof BeanClassLoaderAware) {
				((BeanClassLoaderAware) bean).setBeanClassLoader(getBeanClassLoader());
			}
			// 我们有时候使用BeanFactoryAware去拿BeanFactory,就是在这步设置的
			if (bean instanceof BeanFactoryAware) {
				((BeanFactoryAware) bean).setBeanFactory(AbstractAutowireCapableBeanFactory.this);
			}
		}
	}
复制代码

上面这段代码便是处理其中三种Aware的逻辑,我们分别看看这三种Aware的代码:

BeanNameAware:

public interface BeanNameAware extends Aware {

	void setBeanName(String name);

}
复制代码

BeanClassLoaderAware:

public interface BeanClassLoaderAware extends Aware {

	void setBeanClassLoader(ClassLoader classLoader);

}
复制代码

BeanFactoryAware:

public interface BeanFactoryAware extends Aware {

	void setBeanFactory(BeanFactory beanFactory) throws BeansException;

}
复制代码

这三个Aware其实也就是让我们的bean可以知道自己名字,自己的ClassLoader是哪个,加载自己的BeanFactory是哪个,结合我们上面的代码我们知道其实设置这三个Aware是在bean的生命周期内设置的。

那么还有哪些常见的Aware呢?我自己最常用的一个就是ApplicationContextAware,这个接口的代码我就不贴出来了,因为和上面是一样的,就一个set方法而已,那么又是在哪个地方给我们的bean执行了setApplicationContext的方法呢?我们之前文章中介绍AbstractApplicationContext的refresh方法的时候,其中有个prepareBeanFactory方法,这个方法中有这么一句代码:

深入理解Spring IOC之扩展篇(四)、Aware接口

只看画红框的地方就行了,我们可以看到,spring在这里增加了一个ApplicationContextAwareProcessor,这个玩意的本质上是个BeanPostProcessor,那么这玩意干了什么事情呢?我们一起来看下它的代码:

@Override
	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(new PrivilegedAction<Object>() {
				@Override
				public Object run() {
					invokeAwareInterfaces(bean);
					return null;
				}
			}, acc);
		}
		else {
			invokeAwareInterfaces(bean);
		}

		return bean;
	}
	
	// 上面调用了这个
	private void invokeAwareInterfaces(Object bean) {
		if (bean instanceof Aware) {
			if (bean instanceof EnvironmentAware) {
				((EnvironmentAware) bean).setEnvironment(this.applicationContext.getEnvironment());
			}
			if (bean instanceof EmbeddedValueResolverAware) {
				((EmbeddedValueResolverAware) bean).setEmbeddedValueResolver(
						new EmbeddedValueResolver(this.applicationContext.getBeanFactory()));
			}
			if (bean instanceof ResourceLoaderAware) {
				((ResourceLoaderAware) bean).setResourceLoader(this.applicationContext);
			}
			if (bean instanceof ApplicationEventPublisherAware) {
				((ApplicationEventPublisherAware) bean).setApplicationEventPublisher(this.applicationContext);
			}
			if (bean instanceof MessageSourceAware) {
				((MessageSourceAware) bean).setMessageSource(this.applicationContext);
			}
			if (bean instanceof ApplicationContextAware) {
				((ApplicationContextAware) bean).setApplicationContext(this.applicationContext);
			}
		}
	}
复制代码

这个类只是实现了前置处理这个方法,前置处理什么时候执行的我就不说了,看到这里的人应该是清楚的。这段代码你看我连注释都很少,因为真的很简单,就是检测你是不是实现了这个Aware接口,如果实现了,就给你set上相应的对象而已。其中invokeAwareInterfaces中还有几个其他的Aware,但是说真的,这几个用的都不多,我自己都很少见过业务中使用这几个的,如果读者有兴趣可以自己研究下这几个。

原文 

https://juejin.im/post/5ee58894f265da76c960b01d

本站部分文章源于互联网,本着传播知识、有益学习和研究的目的进行的转载,为网友免费提供。如有著作权人或出版方提出异议,本站将立即删除。如果您对文章转载有任何疑问请告之我们,以便我们及时纠正。

PS:推荐一个微信公众号: askHarries 或者qq群:474807195,里面会分享一些资深架构师录制的视频录像:有Spring,MyBatis,Netty源码分析,高并发、高性能、分布式、微服务架构的原理,JVM性能优化这些成为架构师必备的知识体系。还能领取免费的学习资源,目前受益良多

转载请注明原文出处:Harries Blog™ » 深入理解Spring IOC之扩展篇(四)、Aware接口

赞 (0)
分享到:更多 ()

评论 0

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址