参考文章:
初始化Bean的主要方法在AbstractAutowireCapableBeanFactory.doCreateBean方法中的initializeBean执行,源码逻辑;
protected Object initializeBean(final String beanName, final Object bean, @Nullable RootBeanDefinition mbd) {
//安全模式
if (System.getSecurityManager() != null) {
// 激活 Aware 方法,对特殊的 bean 处理:Aware、BeanClassLoaderAware、BeanFactoryAware
AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
invokeAwareMethods(beanName, bean);
return null;
}, getAccessControlContext());
}
else {
// 激活 Aware 方法,对特殊的 bean 处理:Aware、BeanClassLoaderAware、BeanFactoryAware
invokeAwareMethods(beanName, bean);
}
Object wrappedBean = bean;
if (mbd == null || !mbd.isSynthetic()) {
// 初始化 bean的前置处理
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()) {
// 初始化bean的后置处理
wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
}
return wrappedBean;
}
里面主要有三件事:
- 激活 Aware 方法
- 后置处理器的应用
- 激活自定义的 init 方法
这篇文章先分析第一个激活Aware
Aware接口
接口定义
/**
* Aware 接口为 Spring 容器的核心接口,是一个具有标识作用的超级接口,
* 实现了该接口的 bean 是具有被 Spring 容器通知的能力
*/
public interface Aware {
}
接口常见命名
Aware 接口是一个空接口,实际的方法签名由各个子接口来确定,且该接口通常只会有一个接收单参数的 set 方法,该 set 方法的命名方式为 set + 去掉接口名中的 Aware 后缀。
即 XxxAware 接口,则方法定义为 setXxx(),例如 BeanNameAware(setBeanName)
接口使用策略
Aware 类接口的
setXxx
方法其实就是设置 xxx 属性值的。 Spring 容器中是实现感知并设置属性值的逻辑是在invokeAwareMethods方法中
private void invokeAwareMethods(final String beanName, final Object bean) {
if (bean instanceof Aware) {
// BeanNameAware
if (bean instanceof BeanNameAware) {
((BeanNameAware) bean).setBeanName(beanName);
}
// BeanClassLoaderAware
if (bean instanceof BeanClassLoaderAware) {
ClassLoader bcl = getBeanClassLoader();
if (bcl != null) {
((BeanClassLoaderAware) bean).setBeanClassLoader(bcl);
}
}
// BeanFactoryAware
if (bean instanceof BeanFactoryAware) {
((BeanFactoryAware) bean).setBeanFactory(AbstractAutowireCapableBeanFactory.this);
}
}
}
接口的部分实现类
spring的激活Aware主要涉及的几个接口:
- BeanClassLoaderAware :将 BeanClassLoader 提供给 bean 实例回调
- BeanFactoryAware:将 BeanFactory 提供给 bean 实例回调
- BeanNameAware :在创建此 bean 的 bean工厂中设置 beanName
Aware接口使用的Demo
自定义一个接口
/**
* @author daify
* @date 2019-03-18
*/
public class MyAware implements BeanNameAware,BeanFactoryAware,BeanClassLoaderAware,ApplicationContextAware {
private String beanName;
private BeanFactory beanFactory;
private ClassLoader classLoader;
private ApplicationContext applicationContext;
@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 setBeanName(String s) {
System.out.println("调用了 BeanNameAware 的 setBeanName 方法");
this.beanName = s;
}
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
System.out.println("调用了 ApplicationContextAware 的 setApplicationContext 方法");
this.applicationContext = applicationContext;
}
public void display(){
System.out.println("beanName:" + beanName);
System.out.println("是否为单例:" + beanFactory.isSingleton(beanName));
}
}
测试类分为两种
1、加载资源后,放入bean工厂
public class MyAwareTest01 {
public static void main(String[] args) {
ClassPathResource resource = new ClassPathResource("spring.xml");
DefaultListableBeanFactory factory = new DefaultListableBeanFactory();
XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(factory);
reader.loadBeanDefinitions(resource);
MyAware applicationAware = (MyAware) factory.getBean("myAware");
applicationAware.display();
}
}
打印结果
调用了 BeanNameAware 的 setBeanName 方法
调用了 BeanClassLoaderAware 的 setBeanClassLoader 方法
调用了 BeanFactoryAware 的 setBeanFactory 方法
00:07:06.945 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Finished creating instance of bean 'myAware'
beanName:myAware
是否为单例:true
2、将资源加载进application中
/**
* @author daify
* @date 2019-03-18
*/
public class MyAwareTest02 {
public static void main(String[] args) {
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring.xml");
MyAware applicationAware = (MyAware) applicationContext.getBean("myAware");
applicationAware.display();
}
}
打印结果
调用了 BeanNameAware 的 setBeanName 方法
调用了 BeanClassLoaderAware 的 setBeanClassLoader 方法
调用了 BeanFactoryAware 的 setBeanFactory 方法
调用了 ApplicationContextAware 的 setApplicationContext 方法
beanName:myAware
是否为单例:true
xml内容
<?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-3.0.xsd">
<bean id="myAware" class="com.learn.initbean.MyAware">
</bean>
</beans>
总结
实际上可以看出来,Aware 接口的 set 方法,就是通过
#getBean(...)
方法调用时执行的。Spring 容器在初始化主动检测当前 bean 是否实现了 Aware 接口,如果实现了则回调其 set 方法将相应的参数设置给该 bean ,这个时候该 bean 就从 Spring 容器中取得相应的资源。
接口实现类的列表
- 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的名字
demo地址