spring源碼閱讀筆記(一)
最近工作不忙,抽空閱讀了下《spring源碼深度剖析》,特此做一下記錄。
先說下BeanFactoryPostProcessor接口和BeanPostProcessor接口,這兩個接口都是spring 初始化bean時對外暴露的擴展點。兩個接口名稱看起來很相似,但作用及使用場景卻不同。
1.BeanFactoryPostProcessor
public interface BeanFactoryPostProcessor {
void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException;
}
實現該接口,可以在spring的bean創建之前,修改bean的定義屬性。也就是說,Spring允許BeanFactoryPostProcessor在容器實例化任何其它bean之前讀取配置元數據,並可以根據需要進行修改,例如可以把bean的scope從singleton改爲prototype,也可以把property的值給修改掉。可以同時配置多個BeanFactoryPostProcessor,實現類可以通過實現PriorityOrdered接口來控制各個BeanFactoryPostProcessor的執行次序。
注意:BeanFactoryPostProcessor是在spring容器加載了bean的定義文件之後,在bean實例化之前執行的。接口方法的入參是ConfigurrableListableBeanFactory,使用該參數,可以獲取到相關bean的定義信息。
spring中內置了一些BeanFactoryPostProcessor實現類,常用的有: (org.springframework.beans.factory.config包下)
1.PropertyPlaceholderConfigurer 替換xml中的佔位符爲*.properties文件中的值
2.PropertyOverrideConfigurer 比PropertyPlaceholderConfigurer功能高級些,支持缺省值
3.CustomEditorConfigurer:用來註冊自定義的屬性編輯器
例如自定義一個BeanFactoryPostProcessor:
public MyBeanFactoryPostProcessor implements BeanFactoryPostProcessor {
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory)
throw BeansException {
BeanDefinition bd = beanFactory.getBeanDefinition("myJavaBean");
MutablePropertyValues mpv = bd.getPropertyValues();
mpv.addPropertyValue("propertyName", "newValue");
}
}
xml中配置一下:
<bean class="com.test.MyBeanFactoryPostProcessor" />
2.BeanPostProcessor
public interface BeanPostProcessor {
Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException;
Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException;
}
BeanPostProcessor可以在spring容器實例化bean之後,在執行bean的初始化方法前後,添加一些自己的處
理邏輯。這裏的初始化方法包括bean實現InitializingBean接口的afterPropertiesSet方法和在配置文件中指定
的init-method方法。
其具體的執行過程爲:
spring中有一些內置的BeanPostProcessor實現類,例如
1.org.springframework.context.annotation.CommonAnnotationBeanPostProcessor: 支持@Resource註解的注入
2.org.springframework.beans.factory.annotation.RequiredAnnotationBeanPostProcessor: 支持@Required註解的注入
3.org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor: 支持@Autowired註解的注入
4.org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor:支持@PersistenceUnit和@PersistenceContext註解的注入
5.org.springframework.context.support.ApplicationContextAwareProcessor: 用來爲bean注入ApplicationContext等容器對象
這些註解類會在配置文件中通過配置<context:component-scan base-package="*.*" />後自動進行註冊。
還有aop中的功能也是通過實現BeanPostProcessor接口去做的代理,有興趣的同學可以去看下
AspectJAwareAdvisorAutoProxyCreator類,其父類AbstractAutoProxyCreator中實現了postProcessAfterInitialization
接口完成了對方法的代理。代碼如下:
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
if (bean != null) {
Object cacheKey = getCacheKey(bean.getClass(), beanName);
if (!this.earlyProxyReferences.containsKey(cacheKey)) {
return wrapIfNecessary(bean, beanName, cacheKey);
}
}
return bean;
}
protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
if (beanName != null && this.targetSourcedBeans.containsKey(beanName)) {
return bean;
}
if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {
return bean;
}
if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) {
this.advisedBeans.put(cacheKey, Boolean.FALSE);
return bean;
}
// Create proxy if we have advice.
Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
if (specificInterceptors != DO_NOT_PROXY) {
this.advisedBeans.put(cacheKey, Boolean.TRUE);
Object proxy = createProxy(bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
this.proxyTypes.put(cacheKey, proxy.getClass());
return proxy;
}
this.advisedBeans.put(cacheKey, Boolean.FALSE);
return bean;
}
protected Object createProxy(
Class<?> beanClass, String beanName, Object[] specificInterceptors, TargetSource targetSource) {
ProxyFactory proxyFactory = new ProxyFactory();
// Copy our properties (proxyTargetClass etc) inherited from ProxyConfig.
proxyFactory.copyFrom(this);
if (!shouldProxyTargetClass(beanClass, beanName)) {
// Must allow for introductions; can't just set interfaces to
// the target's interfaces only.
Class<?>[] targetInterfaces = ClassUtils.getAllInterfacesForClass(beanClass, this.proxyClassLoader);
for (Class<?> targetInterface : targetInterfaces) {
proxyFactory.addInterface(targetInterface);
}
}
Advisor[] advisors = buildAdvisors(beanName, specificInterceptors);
for (Advisor advisor : advisors) {
proxyFactory.addAdvisor(advisor);
}
proxyFactory.setTargetSource(targetSource);
customizeProxyFactory(proxyFactory);
proxyFactory.setFrozen(this.freezeProxy);
if (advisorsPreFiltered()) {
proxyFactory.setPreFiltered(true);
}
return proxyFactory.getProxy(this.proxyClassLoader);
}
[proxyFactory]
public Object getProxy(ClassLoader classLoader) {
return createAopProxy().getProxy(classLoader);
}
[JdkDynamicAopProxy]
public Object getProxy(ClassLoader classLoader) {
if (logger.isDebugEnabled()) {
logger.debug("Creating JDK dynamic proxy: target source is " + this.advised.getTargetSource());
}
Class[] proxiedInterfaces = AopProxyUtils.completeProxiedInterfaces(this.advised);
findDefinedEqualsAndHashCodeMethods(proxiedInterfaces);
return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this);
}
如果你有一些其他獨特的需求也可以仿照上面的方式自己寫一個BeanPostProcessor註冊到容器中。
3.InitializingBean和init-method
這兩個方法的調用點是AbstractAutowireCapableBeanFactory類的invokeInitMethods方法:
我們看下代碼:
protected void invokeInitMethods(String beanName, final Object bean, RootBeanDefinition mbd)
throws Throwable {
boolean isInitializingBean = (bean instanceof InitializingBean);
if (isInitializingBean && (mbd == null || !mbd.isExternallyManagedInitMethod("afterPropertiesSet"))) {
if (logger.isDebugEnabled()) {
logger.debug("Invoking afterPropertiesSet() on bean with name '" + beanName + "'");
}
if (System.getSecurityManager() != null) {
try {
AccessController.doPrivileged(new PrivilegedExceptionAction<Object>() {
public Object run() throws Exception {
((InitializingBean) bean).afterPropertiesSet();
return null;
}
}, getAccessControlContext());
}
catch (PrivilegedActionException pae) {
throw pae.getException();
}
}
else {
((InitializingBean) bean).afterPropertiesSet();
}
}
if (mbd != null) {
String initMethodName = mbd.getInitMethodName();
if (initMethodName != null && !(isInitializingBean && "afterPropertiesSet".equals(initMethodName)) &&
!mbd.isExternallyManagedInitMethod(initMethodName)) {
invokeCustomInitMethod(beanName, bean, mbd);
}
}
}
但是invokeInitMethods方法又是在哪裏調用的呢?是同一個類中的initializeBean方法調用的,代碼如下:
protected Object initializeBean(final String beanName, final Object bean, RootBeanDefinition mbd) {
if (System.getSecurityManager() != null) {
AccessController.doPrivileged(new PrivilegedAction<Object>() {
public Object run() {
invokeAwareMethods(beanName, bean);
return null;
}
}, getAccessControlContext());
}
else {
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接口的一些相關方法,然後是調用BeanPostProcessor接口的前置處理,
然後調用上面的bean初始化方法,然後是BeanPostProcessor的後置處理,這正好符合了上圖中描述的調用順序。
其中Aware有很多子接口,像BeanNameAware,BeanClassLoaderAware,BeanFactoryAware等等,用戶可以編寫實現
了這些接口的bean,這樣在spring回調aware相關接口的時候獲取到一些容器的相關信息。
下面簡單說下使用InitializingBean和init-method方法初始化bean的區別:
1.實現InitializingBean接口是直接調用afterPropertiesSet方法,比通過反射調用init-method指定的方法效率相對來說要高點。
但是init-method方式消除了對spring的依賴
2:如果調用afterPropertiesSet方法時出錯,則不調用init-method指定的方法。