【spring源码分析】IOC容器初始化——查漏补缺(一)
前言:在【spring源码分析】IOC容器初始化(十一)中提到了初始化bean的三个步骤:
- 激活Aware方法。
- 后置处理器应用(before/after)。
- 激活自定义的init方法。
这里我们就来看下Spring是如何激活Aware方法的。
Aware是什么
Aware是一个空接口,包路径为:org.springframework.beans.factory.Aware,它具有标识作用,实现了该接口的bean具有被Spring容器通知的能力,通知的方式采用回调的方式。
由于Aware是一个空接口,实际的方法签名由各个子类来确定,其该接口通常只会有一个接收单参数的set方法,该set方法的命名方式为set+去掉接口中的Aware后缀,即:setxxx(),那Spring中是如何处理实现Aware接口的bean的呢。在invokeAwareMethods方法中可以看到如下代码:
1 // AbstractAutowireCapableBeanFactory 2 private void invokeAwareMethods(final String beanName, final Object bean) { 3 if (bean instanceof Aware) { 4 // BeanNameAware 5 if (bean instanceof BeanNameAware) { 6 ((BeanNameAware) bean).setBeanName(beanName); 7 } 8 // BeanClassLoaderAware 9 if (bean instanceof BeanClassLoaderAware) { 10 ClassLoader bcl = getBeanClassLoader(); 11 if (bcl != null) { 12 ((BeanClassLoaderAware) bean).setBeanClassLoader(bcl); 13 } 14 } 15 // BeanFactoryAware 16 if (bean instanceof BeanFactoryAware) { 17 ((BeanFactoryAware) bean).setBeanFactory(AbstractAutowireCapableBeanFactory.this); 18 } 19 } 20 }
分析:
首先判断bean是否实现了Aware接口,如果是则调用实例的setXXX()方法给实例设置xxx属性,在invokeAwareMethods方法中,主要处理BeanNameAware、BeanClassLoaderAware、BeanFactoryAware三种接口,也从侧面证实了Spring只会处理实现了这三种接口中任意一个的bean实例。
Aware示例演示
下面就演示Spring是如何处理实现这三个接口的bean的:
1 public class UserDefinedAware implements BeanNameAware, BeanClassLoaderAware, BeanFactoryAware { 2 3 private String name; 4 private ClassLoader classLoader; 5 private BeanFactory beanFactory; 6 7 @Override 8 public void setBeanName(String name) { 9 System.out.println("调用了 BeanNameAware 的 setBeanName方法"); 10 this.name = name; 11 } 12 13 @Override 14 public void setBeanClassLoader(ClassLoader classLoader) { 15 System.out.println("调用了 BeanClassLoader 的 setBeanClassLoader 方法"); 16 this.classLoader = classLoader; 17 } 18 19 @Override 20 public void setBeanFactory(BeanFactory beanFactory) throws BeansException { 21 System.out.println("调用了 BeanFactoryAware 的 setBeanFactory 方法"); 22 this.beanFactory = beanFactory; 23 } 24 25 public void showMsg() { 26 System.out.println("beanName=" + this.name); 27 System.out.println("classLoader=" + this.classLoader.getClass()); 28 System.out.println("是否为单例=" + beanFactory.isSingleton(this.name)); 29 } 30 }
测试方法如下:
1 /** 2 * Aware接口演示 3 */ 4 @Test 5 public void awareTest() { 6 ApplicationContext context = new ClassPathXmlApplicationContext("classpath*:com/dev/config/aware/aware.xml"); 7 UserDefinedAware userDefinedAware = context.getBean(UserDefinedAware.class); 8 userDefinedAware.showMsg(); 9 }
输出结果如下:
Aware总结
从以上示例基本上可以了解 Aware接口 真正的含义:感知,其实是Spring容器在初始化主动检测当前bean是否实现了Aware接口,如果实现了则回调其set方法将相应的参数设置给该bean,这个时候该bean就从Spring容器中取得了相应的资源。所以Aware接口的作用就是让实现该接口的bean能从Spring容器中取得相应的资源。这里如name、ClassLoader、beanFactory。
下面列出一些常用的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的名字
by Shawn Chen,2019.04.29,晚上。