Spring bean初始化擴展之Aware源碼解析
認識Aware接口
package org.springframework.beans.factory;
/**
* A marker superinterface indicating that a bean is eligible to be notified by the
* Spring container of a particular framework object through a callback-style method.
* The actual method signature is determined by individual subinterfaces but should
* typically consist of just one void-returning method that accepts a single argument.
*
* <p>Note that merely implementing {@link Aware} provides no default functionality.
* Rather, processing must be done explicitly, for example in a
* {@link org.springframework.beans.factory.config.BeanPostProcessor}.
* Refer to {@link org.springframework.context.support.ApplicationContextAwareProcessor}
* for an example of processing specific {@code *Aware} interface callbacks.
*
* @author Chris Beams
* @author Juergen Hoeller
* @since 3.1
*/
public interface Aware {
}
可以看到Aware是一個空接口,沒有任何方法,它類似於java.io.Serializable接口,作用是標識某一類接口。Aware是Spring容器中非常重要的一個接口。有很多接口繼承了Aware接口,如BeanFactoryAware。而實現了這些接口的bean將會被Spring容器回調通知(即調用接口中得set方法)。一般繼承Aware接口的接口,會定義相應setXxx接口方法,如BeanFactoryAware定義了setBeanFactory方法,spring容器會在初始化bean時,會調用bean實現的Aware接口的setXxx方法,這個調用過程在上一篇博客有介紹。
舉例BeanFactoryAware
package org.springframework.beans.factory;
import org.springframework.beans.BeansException;
/**
* Interface to be implemented by beans that wish to be aware of their
* owning {@link BeanFactory}.
*
* <p>For example, beans can look up collaborating beans via the factory
* (Dependency Lookup). Note that most beans will choose to receive references
* to collaborating beans via corresponding bean properties or constructor
* arguments (Dependency Injection).
*
* <p>For a list of all bean lifecycle methods, see the
* {@link BeanFactory BeanFactory javadocs}.
*
* @author Rod Johnson
* @author Chris Beams
* @since 11.03.2003
* @see BeanNameAware
* @see BeanClassLoaderAware
* @see InitializingBean
* @see org.springframework.context.ApplicationContextAware
*/
public interface BeanFactoryAware extends Aware {
/**
* Callback that supplies the owning factory to a bean instance.
* <p>Invoked after the population of normal bean properties
* but before an initialization callback such as
* {@link InitializingBean#afterPropertiesSet()} or a custom init-method.
* @param beanFactory owning BeanFactory (never {@code null}).
* The bean can immediately call methods on the factory.
* @throws BeansException in case of initialization errors
* @see BeanInitializationException
*/
void setBeanFactory(BeanFactory beanFactory) throws BeansException;
}
spring調用Aware的setXxx進行回調通知
AbstractAutowireCapableBeanFactory中初始化bean的源碼
protected Object initializeBean(final String beanName, final Object bean, @Nullable RootBeanDefinition mbd) {
if (System.getSecurityManager() != null) {
AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
invokeAwareMethods(beanName, bean);
return null;
}, getAccessControlContext());
}
else {
//調用調用此方法進行部分Aware接口的回調
invokeAwareMethods(beanName, bean);
}
Object wrappedBean = bean;
if (mbd == null || !mbd.isSynthetic()) {
//調用後置處理器的前置方法
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()) {
//調用後置處理器的後置方法
wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
}
return wrappedBean;
}
可以看到是初始化bean的幾個步驟裏面,在第一步進行了激活Aware接口的方法,invokeAwareMethods,其實現如下:
private void invokeAwareMethods(final String beanName, final Object bean) {
//這裏主要處理 BeanNameAware BeanClassLoaderAware BeanFactoryAware這三個接口,可以看到主要是調用bean實現的Aware中的setXxx方法
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);
}
}
}
可以看到這裏主要處理了BeanNameAware BeanClassLoaderAware BeanFactoryAware這三個接口,通過調用setXxx方法,將屬性設置給bean。
示例代碼
工程結構
這裏用ApplicationContextAware作爲示例代碼的接口。以下是工程結構
MyAware
package spring.aware;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
public class MyAware implements ApplicationContextAware {
private ApplicationContext myapplicationContext;
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
myapplicationContext = applicationContext;
System.out.println("spring容器已調用setApplicationContext進行回調通知,myapplicationContext=" + myapplicationContext);
}
public ApplicationContext getMyapplicationContext() {
return myapplicationContext;
}
}
AwareConfig
package spring.aware;
import org.springframework.context.annotation.*;
@Configuration
public class AwareConfig {
@Bean(value = "myAware")
public MyAware myAware() {
return new MyAware();
}
}
AwareTest
package spring.aware.test;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import spring.aware.AwareConfig;
import spring.aware.MyAware;
public class AwareTest {
@Test
public void testAware() {
ApplicationContext applicationContext = new AnnotationConfigApplicationContext(AwareConfig.class);
MyAware myAware = (MyAware) applicationContext.getBean("myAware");
System.out.println("從容器中獲取的myAware="+myAware + ",其applicationContext屬性=" + myAware.getMyapplicationContext());
}
}
運行結果
方法調用棧分析
前面我們分析了BeanNameAware BeanClassLoaderAware BeanFactoryAware這三個接口是在初始化bean的第一步就做了處理。通過上圖這個調用棧可以看到,其它實現的Aware的接口,則通過相應的後置處理器(如這裏的ApplicationContextAwareProcessor)進行間接處理,最終調用了相應的setXxx方法。
ApplicationContextAwareProcessor
@Override
@Nullable
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<Object>) () -> {
invokeAwareInterfaces(bean);
return null;
}, acc);
}
else {
//調用激活Aware接口
invokeAwareInterfaces(bean);
}
return bean;
}
private void invokeAwareInterfaces(Object bean) {
//根據不同接口調用相應的setXxx方法
if (bean instanceof Aware) {
if (bean instanceof EnvironmentAware) {
((EnvironmentAware) bean).setEnvironment(this.applicationContext.getEnvironment());
}
if (bean instanceof EmbeddedValueResolverAware) {
((EmbeddedValueResolverAware) bean).setEmbeddedValueResolver(this.embeddedValueResolver);
}
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的調用時機,也應該是通過相應的後置處理器進行處理,間接調用相應的setXxx方法。