這個類的設計,和Spring ioc的結合,簡直是吊炸天,實現了根據配置把spring ioc里面的bean替換為相應的代理對象,也為AspectJ的整合提供了支持,讓我們來看看Spring是如何做到這種更高級的聲明式Aop
1.類結構
這邊的講解線路分為2塊
- Spring的Bean后處理器,SmartInstantiationAwareBeanPostProcessor->InstantiationAwareBeanPostProcessor->BeanPostProcessor
- DefaultAdvisorAutoProxyCreator的主繼承線,DefaultAdvisorAutoProxyCreator->AbstractAdvisorAutoProxyCreator->AbstractAutoProxyCreator->ProxyProcessorSupport->ProxyConfig
講解之前可以看下我寫的這塊的demo ,可以一邊看解析,一邊打斷點調試
2.解析
2.1 Spring Bean后處理器
在講這三個接口之前,我們先來看下Spring bean的生命周期,不知道這個流程,也很難理解這三個接口的作用
閱讀AbstractAutowireCapableBeanFactory的doCreateBean和destroyBean方法,我們能清楚看到Spring bean創建的整個生命周期,具體如下
- 調用InstantiationAwareBeanPostProcessor的postProcessBeforeInstantiation(Class<?> beanClass, String beanName)
- bean實例化
- 調用InstantiationAwareBeanPostProcessor的postProcessAfterInstantiation(Object bean, String beanName)
- 調用InstantiationAwareBeanPostProcessor的postProcessPropertyValues(PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName)
- bean注入properties
- 分別調用BeanNameAware,BeanClassLoaderAware,BeanFactoryAware中的方法
- 調用BeanPostProcessor的postProcessBeforeInitialization(Object bean, String beanName)
- 調用InitializingBean的afterPropertiesSet方法
- 調用自定義初始化方法
- 調用BeanPostProcessor的postProcessAfterInitialization(Object bean, String beanName)
- 調用DisposableBean的destroy()方法
- 調用自定義銷毀方法
下面分別介紹這三個bean后處理器的功能
public interface BeanPostProcessor {
Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException;
Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException;
}
從生命周期中可以看到,BeanPostProcessor中的這兩個方法分別會在bean調用init方法前后回調,用于對已經注入properties的bean對象進行修改,把bean替換成代理對象會在postProcessAfterInitialization中執行
public interface InstantiationAwareBeanPostProcessor extends BeanPostProcessor {
Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException;
boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException;
PropertyValues postProcessPropertyValues(
PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) throws BeansException;
}
postProcessBeforeInstantiation和postProcessAfterInstantiation分別在bean實例化前后回調
postProcessPropertyValues將在注入properties之前觸發,可以對整理好的properties進行修改
public interface SmartInstantiationAwareBeanPostProcessor extends InstantiationAwareBeanPostProcessor {
Class<?> predictBeanType(Class<?> beanClass, String beanName) throws BeansException;
Constructor<?>[] determineCandidateConstructors(Class<?> beanClass, String beanName) throws BeansException;
Object getEarlyBeanReference(Object bean, String beanName) throws BeansException;
}
predictBeanType用于提前給出postProcessBeforeInstantiation生成的bean的類型
determineCandidateConstructors用于bean初始化的時候決定調用哪一個構造函數,如果針對某個類型的bean設置了這個回調,會采用回調設置的構造函數初始化bean,具體邏輯代碼如下
Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);
if (ctors != null ||
mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_CONSTRUCTOR ||
mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args)) {
return autowireConstructor(beanName, mbd, ctors, args);
}
getEarlyBeanReference用于解決循環依賴的問題
這三個bean后處理器講解好了 ,現在我們開始講DefaultAdvisorAutoProxyCreator是怎么實現自動配置代理對象的
2.2 DefaultAdvisorAutoProxyCreator
從類結構圖中可以看到主要的繼承鏈,DefaultAdvisorAutoProxyCreator->AbstractAdivisorAutoProxyCreator->AbstractAutoProxyCreator->ProxyProcessorSupport->ProxyConfig
ProxyConfig就不多講了,之前講過,我們來分別介紹下其他4個類的作用
2.2.1 ProxyProcessorSupport
看名字就知道是一個為代理生成提供支持的工具類,主要提供evaluateProxyInterfaces方法用來根據BeanClass對ProxyFactory中的代理方式進行配置,方法如下
protected void evaluateProxyInterfaces(Class<?> beanClass, ProxyFactory proxyFactory) {
Class<?>[] targetInterfaces = ClassUtils.getAllInterfacesForClass(beanClass, getProxyClassLoader());
boolean hasReasonableProxyInterface = false;
for (Class<?> ifc : targetInterfaces) {
if (!isConfigurationCallbackInterface(ifc) && !isInternalLanguageInterface(ifc) &&
ifc.getMethods().length > 0) {
hasReasonableProxyInterface = true;
break;
}
}
if (hasReasonableProxyInterface) {
// Must allow for introductions; can't just set interfaces to the target's interfaces only.
for (Class<?> ifc : targetInterfaces) {
proxyFactory.addInterface(ifc);
}
}
else {
proxyFactory.setProxyTargetClass(true);
}
}
這里會判斷是否可以代理接口,如果可以,用proxyFactory的addInterface方法把設置所有存在的接口類,如果不可以,那么調用setProxyTargetClass(true),配置為代理類
同時我們可以注意到這個類實現了Ordered接口,并且設置order = Ordered.LOWEST_PRECEDENCE,這是為了讓生成代理的后處理器最后一個執行(原因可能是在之前的后處理器可能也會把Advisor加進去,那樣就會出現不生效的問題)
2.2.2 AbstractAutoProxyCreator
這個類是這個繼承鏈中最核心的類,因為生成代理的邏輯封裝在這里
它實現SmartInstantiationAwareBeanPostProcessor,在回調方法里封裝了把bean對象替換為代理對象的邏輯,在getEarlyBeanReference,postProcessBeforeInstantiation,postProcessAfterInitialization均能產生代理,postProcessBeforeInstantiation需要在配置了TargetSourceCreator之后才能生效,目前沒有遇到這個場景,所以忽略,getEarlyBeanReference是為了解決循環依賴重寫的,用來提前長生代理類,postProcessAfterInitialization在getEarlyBeanReference沒有生效的情況下會被調用,這兩個方法都調用了wrapIfNecessary來生成代理,我們來看下這個方法
protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
if (beanName != null && this.targetSourcedBeans.contains(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;
}
wrapIfNecessary首先會通過getAdvicesAndAdvisorsForBean得到攔截器集合,這個會交給子類實現,子類可以設計不同的策略來獲取攔截器集合,如果getAdvicesAndAdvisorsForBean返回的集合不為空,就調用createProxy生成代理
protected Object createProxy(
Class<?> beanClass, String beanName, Object[] specificInterceptors, TargetSource targetSource) {
if (this.beanFactory instanceof ConfigurableListableBeanFactory) {
AutoProxyUtils.exposeTargetClass((ConfigurableListableBeanFactory) this.beanFactory, beanName, beanClass);
}
ProxyFactory proxyFactory = new ProxyFactory();
proxyFactory.copyFrom(this);
if (!proxyFactory.isProxyTargetClass()) {
if (shouldProxyTargetClass(beanClass, beanName)) {
proxyFactory.setProxyTargetClass(true);
}
else {
evaluateProxyInterfaces(beanClass, proxyFactory);
}
}
Advisor[] advisors = buildAdvisors(beanName, specificInterceptors);
proxyFactory.addAdvisors(advisors);
proxyFactory.setTargetSource(targetSource);
customizeProxyFactory(proxyFactory);
proxyFactory.setFrozen(this.freezeProxy);
if (advisorsPreFiltered()) {
proxyFactory.setPreFiltered(true);
}
return proxyFactory.getProxy(getProxyClassLoader());
}
createProxy還是比較熟悉的,在上節鋪墊過,使用了ProxyFactory的編程式Aop生成代理
通過這幾個回調,巧妙的在spring生命周期內把我們生成代理bean的行為注入了
2.2.3 AbstractAdivisorAutoProxyCreator
AbstractAdivisorAutoProxyCreator主要實現了AbstractAutoProxyCreator提供的擴展點方法getAdvicesAndAdvisorsForBean,用來設置攔截器集合
protected Object[] getAdvicesAndAdvisorsForBean(Class<?> beanClass, String beanName, TargetSource targetSource) {
List<Advisor> advisors = findEligibleAdvisors(beanClass, beanName);
if (advisors.isEmpty()) {
return DO_NOT_PROXY;
}
return advisors.toArray();
}
getAdvicesAndAdvisorsForBean中會通過findEligibleAdvisors來獲取攔截器集合,如果不存在返回DO_NOT_PROXY,來看下findEligibleAdvisors
protected List<Advisor> findEligibleAdvisors(Class<?> beanClass, String beanName) {
List<Advisor> candidateAdvisors = findCandidateAdvisors();
List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);
extendAdvisors(eligibleAdvisors);
if (!eligibleAdvisors.isEmpty()) {
eligibleAdvisors = sortAdvisors(eligibleAdvisors);
}
return eligibleAdvisors;
}
protected List<Advisor> findCandidateAdvisors() {
return this.advisorRetrievalHelper.findAdvisorBeans();
}
在findEligibleAdvisors中,通過findCandidateAdvisors來獲取候選的adivisors,內部使用了advisorRetrievalHelper.findAdvisorBeans,其實就是從beanfactory獲取實現Advisor接口的bean,然后可以在這個方法里面看到
public List<Advisor> findAdvisorBeans() {
// Determine list of advisor bean names, if not cached already.
String[] advisorNames = null;
synchronized (this) {
advisorNames = this.cachedAdvisorBeanNames;
if (advisorNames == null) {
// Do not initialize FactoryBeans here: We need to leave all regular beans
// uninitialized to let the auto-proxy creator apply to them!
advisorNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
this.beanFactory, Advisor.class, true, false);
this.cachedAdvisorBeanNames = advisorNames;
}
}
if (advisorNames.length == 0) {
return new LinkedList<Advisor>();
}
List<Advisor> advisors = new LinkedList<Advisor>();
for (String name : advisorNames) {
if (isEligibleBean(name)) {
if (this.beanFactory.isCurrentlyInCreation(name)) {
if (logger.isDebugEnabled()) {
logger.debug("Skipping currently created advisor '" + name + "'");
}
}
else {
try {
advisors.add(this.beanFactory.getBean(name, Advisor.class));
}
catch (BeanCreationException ex) {
Throwable rootCause = ex.getMostSpecificCause();
if (rootCause instanceof BeanCurrentlyInCreationException) {
BeanCreationException bce = (BeanCreationException) rootCause;
if (this.beanFactory.isCurrentlyInCreation(bce.getBeanName())) {
if (logger.isDebugEnabled()) {
logger.debug("Skipping advisor '" + name +
"' with dependency on currently created bean: " + ex.getMessage());
}
// Ignore: indicates a reference back to the bean we're trying to advise.
// We want to find advisors other than the currently created bean itself.
continue;
}
}
throw ex;
}
}
}
}
return advisors;
}
注意到有一個isEligibleBean方法,在AbstractAdivisorAutoProxyCreator使用了BeanFactoryAdvisorRetrievalHelper擴展子類,重定義了isEligibleBean方法,如下
private class BeanFactoryAdvisorRetrievalHelperAdapter extends BeanFactoryAdvisorRetrievalHelper {
public BeanFactoryAdvisorRetrievalHelperAdapter(ConfigurableListableBeanFactory beanFactory) {
super(beanFactory);
}
@Override
protected boolean isEligibleBean(String beanName) {
return AbstractAdvisorAutoProxyCreator.this.isEligibleAdvisorBean(beanName);
}
}
把BeanFactoryAdvisorRetrievalHelper中的isEligibleBean委托給了AbstractAdvisorAutoProxyCreator實現,AbstractAdvisorAutoProxyCreator中默認實現如下
protected boolean isEligibleAdvisorBean(String beanName) {
return true;
}
這個實現默認為不過濾,可以讓子類去實現
2.2.4 DefaultAdvisorAutoProxyCreator
DefaultAdvisorAutoProxyCreator實現AbstractAdivisorAutoProxyCreator開放的擴展點isEligibleAdvisorBean,邏輯很簡單,如下
protected boolean isEligibleAdvisorBean(String beanName) {
return (!isUsePrefix() || beanName.startsWith(getAdvisorBeanNamePrefix()));
}
通過配置的prefix來過濾adivisor bean
2.3 InfrastructureAdvisorAutoProxyCreator
InfrastructureAdvisorAutoProxyCreator也實現了AbstractAdivisorAutoProxyCreator開放的擴展點isEligibleAdvisorBean
@Override
protected boolean isEligibleAdvisorBean(String beanName) {
return (this.beanFactory.containsBeanDefinition(beanName) &&
this.beanFactory.getBeanDefinition(beanName).getRole() == BeanDefinition.ROLE_INFRASTRUCTURE);
}
可以看到,這個過濾條件是,只選擇框架級別(beanDefinitiod的role為ROLE_INFRASTRUCTURE)的Adivisor來進行對符合條件的對象進行織入,生成代理
3.總結
DefaultAdvisorAutoProxyCreator主要實現的功能為使用bean后處理器的回調函數,根據ioc容器配置的advisor,來對ioc 容器中的其他bean生成相應代理