IOC之Aware接口
AbstractAutowireCapableBeanFactory 的 doCreateBean(final String beanName, final RootBeanDefinition mbd, final Object[] args)
方法,主要干三件事情:
- 实例化 bean 对象:
createBeanInstance(String beanName, RootBeanDefinition mbd, Object[] args)
方法。
- 属性注入:
populateBean(String beanName, RootBeanDefinition mbd, BeanWrapper bw)
方法。
- 初始化 bean 对象:
initializeBean(final String beanName, final Object bean, RootBeanDefinition mbd)
方法。
而初始化 bean 对象时,也是干了三件事情:
- 激活 Aware 方法
- 后置处理器的应用
- 激活自定义的 init 方法
Aware
接口
1 2 3
| public interface Aware { }
|
Aware 接口为 Spring 容器的核心接口,是一个具有标识作用的超级接口,实现了该接口的 bean 是具有被 Spring 容器通知的能力,通知的方式是采用回调的方式。
Aware 接口为 Spring 容器的核心接口,是一个具有标识作用的超级接口,实现了该接口的 bean 是具有被 Spring 容器通知的能力,通知的方式是采用回调的方式。
Aware 的子接口需要提供一个 setXxx
方法,我们知道 set 是设置属性值的方法,即 Aware 类接口的 setXxx
方法其实就是设置 xxx 属性值的。 Aware 的含义是感知的、感应的,那么在 Spring 容器中是如何实现感知并设置属性值得呢?我们可以从初始化 bean 中的激活 Aware 的方法 invokeAwareMethods(final String beanName, final Object bean)
中看到一点点:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
|
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); } } }
|
- 首先,判断 bean 实例是否属于 Aware 接口的范畴,如果是的话,则调用实例的
setXxx()
方法给实例设置 xxx 属性值,在 invokeAwareMethods(...)
方法,主要是设置 beanName,beanClassLoader、BeanFactory 中三个属性值。
Aware子类
Aware
有诸多子类,比较熟悉的BeanClassLoaderAware
、BeanFactoryAware
、BeanNameAware
:
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 40 41
| public interface BeanClassLoaderAware extends Aware {
void setBeanClassLoader(ClassLoader classLoader);
}
public interface BeanFactoryAware extends Aware {
void setBeanFactory(BeanFactory beanFactory) throws BeansException;
}
public interface BeanNameAware extends Aware {
void setBeanName(String name);
}
public interface ApplicationContextAware extends Aware {
void setApplicationContext(ApplicationContext applicationContext) throws BeansException;
}
|
实例
JavaBean
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
| public class TestAware implements ApplicationContextAware,BeanNameAware, BeanClassLoaderAware, BeanFactoryAware { private ClassLoader classLoader; private String beanName; private BeanFactory beanFactory; private ApplicationContext applicationContext; @Override public void setBeanName(String name) { System.out.println("调用了BeanNameAware的setBeanName..."); this.beanName = name; }
@Override public void setBeanClassLoader(ClassLoader classLoader) { System.out.println("调用了BeanClassLoaderAware的setBeanClassLoader..."); this.classLoader = classLoader; }
@Override public void setBeanFactory(BeanFactory beanFactory) throws BeansException { System.out.println("调用了BeanFactoryAware的setBeanFactory"); this.beanFactory =beanFactory; }
@Override public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { System.out.println("调用了ApplicationContextAware的setApplicationContext"); this.applicationContext = applicationContext; }
public void display(){ System.out.println("beanName:" + this.beanName); System.out.println("是否为单例:" + this.beanFactory.isPrototype(this.beanName)); } }
|
spring配置文件
1 2 3 4 5 6
| <?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> <bean id="testAware" class="com.jievhaha.TestAware" scope="prototype"></bean> </beans>
|
测试
1 2 3 4 5 6 7 8 9 10
| public class MyApplication { public static void main(String[] args) { ClassPathResource classPathResource = new ClassPathResource("applicationContext.xml"); DefaultListableBeanFactory defaultListableBeanFactory = new DefaultListableBeanFactory(); XmlBeanDefinitionReader xmlBeanDefinitionReader = new XmlBeanDefinitionReader(defaultListableBeanFactory); xmlBeanDefinitionReader.loadBeanDefinitions(classPathResource); TestAware testAware = (TestAware) defaultListableBeanFactory.getBean("testAware"); testAware.display(); } }
|
结果:
1 2 3 4 5
| 调用了BeanNameAware的setBeanName... 调用了BeanClassLoaderAware的setBeanClassLoader... 调用了BeanFactoryAware的setBeanFactory beanName:testAware 是否为单例:true
|
1 2 3 4 5 6 7 8
| public class MyApplication { public static void main(String[] args) { ApplicationContext app = new ClassPathXmlApplicationContext("applicationContext.xml");
TestAware testAware = (TestAware) app.getBean("testAware"); testAware.display(); } }
|
结果,较上边的测试多调用了setApplicationContext()
方法:
1 2 3 4 5 6
| 调用了BeanNameAware的setBeanName... 调用了BeanClassLoaderAware的setBeanClassLoader... 调用了BeanFactoryAware的setBeanFactory 调用了ApplicationContextAware的setApplicationContext beanName:testAware 是否为单例:true
|
总结
常见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的名字