Spring源碼解析 -- 讀取bean元數據
spring源碼解析 -- 構造bean
spring源碼解析 -- 注入屬性
spring源碼解析 -- Spring Context
Spring源碼解析 -- AOP原理(1)
Spring源碼解析 -- AOP原理(2)
Spring源碼解析 -- SpringMvc原理java
源碼分析基於spring 4.3.x
本文經過閱讀Spring源碼,分析Spring AOP的功能是如何實現的。
關於閱讀源碼的思路,可參考 -- 如何閱讀java源碼正則表達式
首先,明確幾個概念
pointcut:切入點,根據方法名或者正則表達式去攔截一個方法。
advice:通知,在攔截到方法執行前或執行後的加強操做。
aspect:切面,一個切面能夠包括多個切入點和通知,spring內部的切入點和通知是無序的。
advisor:只有一個通知和一個切入點的單元切面,能夠看作一種特殊的aspect。spring
開始閱讀源碼前,本文主要關注的幾個問題:express
<aop:aspectj-autoproxy/>
元素的做用<aop:aspectj-autoproxy/>
的做用aspectj-autoproxy是spring內部定義的標籤。
前面解析Spring讀取bean元數據的文章說過,在spring中除了標籤,其餘標籤須要編寫一個NamespaceHandlerSupport實現類來完成標籤解析工做。
在spring源碼中搜索一下,就能夠發現aspectj-autoproxy的解析類AopNamespaceHandler緩存
public void init() {
this.registerBeanDefinitionParser("config", new ConfigBeanDefinitionParser());
this.registerBeanDefinitionParser("aspectj-autoproxy", new AspectJAutoProxyBeanDefinitionParser());
this.registerBeanDefinitionDecorator("scoped-proxy", new ScopedProxyBeanDefinitionDecorator());
this.registerBeanDefinitionParser("spring-configured", new SpringConfiguredBeanDefinitionParser());
}
複製代碼
而AspectJAutoProxyBeanDefinitionParser類負責對aspectj-autoproxy標籤進行解析: AspectJAutoProxyBeanDefinitionParser#parsebash
public BeanDefinition parse(Element element, ParserContext parserContext) {
AopNamespaceUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(parserContext, element);
extendBeanDefinition(element, parserContext);
return null;
}
複製代碼
AopNamespaceUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary -> AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary微信
public static BeanDefinition registerAspectJAnnotationAutoProxyCreatorIfNecessary(
BeanDefinitionRegistry registry, Object source) {
return registerOrEscalateApcAsRequired(AnnotationAwareAspectJAutoProxyCreator.class, registry, source);
}
複製代碼
這裏將AnnotationAwareAspectJAutoProxyCreator注入到spring上下文環境中。
AnnotationAwareAspectJAutoProxyCreator是一個關鍵的類,繼承了BeanPostProcessor接口,它負責完成建立切面工做。源碼分析
AbstractAutoProxyCreator#postProcessAfterInitialization -> AbstractAutoProxyCreator#wrapIfNecessary (AbstractAutoProxyCreator是AnnotationAwareAspectJAutoProxyCreator的父類)post
protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
...
Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null); // #1
if (specificInterceptors != DO_NOT_PROXY) {
this.advisedBeans.put(cacheKey, Boolean.TRUE);
Object proxy = createProxy(
bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean)); // #2
this.proxyTypes.put(cacheKey, proxy.getClass());
return proxy;
}
this.advisedBeans.put(cacheKey, Boolean.FALSE);
return bean;
}
複製代碼
#1
根據bean元數據構造通知和單元切面
#2
建立代理對象ui
getAdvicesAndAdvisorsForBean -> AbstractAdvisorAutoProxyCreator#getAdvicesAndAdvisorsForBean -> AbstractAdvisorAutoProxyCreator#findEligibleAdvisors
protected List<Advisor> findEligibleAdvisors(Class<?> beanClass, String beanName) {
List<Advisor> candidateAdvisors = findCandidateAdvisors(); // #1
List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName); // #2
extendAdvisors(eligibleAdvisors); // #3
if (!eligibleAdvisors.isEmpty()) {
eligibleAdvisors = sortAdvisors(eligibleAdvisors); // #4
}
return eligibleAdvisors;
}
複製代碼
這是一個很是重要的方法,實現了幾個關鍵步驟
#1
findCandidateAdvisors -- 查找全部的單元切面(第一次會建立)
#2
findAdvisorsThatCanApply -- 根據目標bean的class過濾一部分的單元切面
#3
extendAdvisors -- 擴充單元切面列表,spring會根據須要添加一些內部使用的單元切面
#4
sortAdvisors -- 對單元切面排序
findCandidateAdvisors -> AnnotationAwareAspectJAutoProxyCreator#findCandidateAdvisors -> BeanFactoryAspectJAdvisorsBuilder#buildAspectJAdvisors
public List<Advisor> buildAspectJAdvisors() {
List<String> aspectNames = this.aspectBeanNames;
if (aspectNames == null) {
synchronized (this) {
aspectNames = this.aspectBeanNames;
if (aspectNames == null) { // #1
List<Advisor> advisors = new LinkedList<Advisor>();
aspectNames = new LinkedList<String>();
String[] beanNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
this.beanFactory, Object.class, true, false);
for (String beanName : beanNames) { // #2
if (!isEligibleBean(beanName)) { // #3
continue;
}
// We must be careful not to instantiate beans eagerly as in this case they
// would be cached by the Spring container but would not have been weaved.
Class<?> beanType = this.beanFactory.getType(beanName);
if (beanType == null) {
continue;
}
if (this.advisorFactory.isAspect(beanType)) { // #4
aspectNames.add(beanName);
AspectMetadata amd = new AspectMetadata(beanType, beanName); // #5
if (amd.getAjType().getPerClause().getKind() == PerClauseKind.SINGLETON) {
MetadataAwareAspectInstanceFactory factory =
new BeanFactoryAspectInstanceFactory(this.beanFactory, beanName);
List<Advisor> classAdvisors = this.advisorFactory.getAdvisors(factory); // #6
if (this.beanFactory.isSingleton(beanName)) { // #7
this.advisorsCache.put(beanName, classAdvisors);
}
else {
this.aspectFactoryCache.put(beanName, factory);
}
advisors.addAll(classAdvisors); // #8
}
else {
// Per target or per this.
if (this.beanFactory.isSingleton(beanName)) {
throw new IllegalArgumentException("Bean with name '" + beanName +
"' is a singleton, but aspect instantiation model is not singleton");
}
MetadataAwareAspectInstanceFactory factory =
new PrototypeAspectInstanceFactory(this.beanFactory, beanName);
this.aspectFactoryCache.put(beanName, factory);
advisors.addAll(this.advisorFactory.getAdvisors(factory));
}
}
}
this.aspectBeanNames = aspectNames;
return advisors;
}
}
}
... #9
}
複製代碼
#1
典型的double check
#2
遍歷全部的bean
#3
判斷是否爲合格的切面類
#4
是否爲切面類(是否有Aspect註解)
#5
獲取切面信息
#6
構建一系列的單元切面
#7
加入緩存
#8
加入結果
#9
緩存不爲空,從緩存中獲取數據返回
步驟#6
調用ReflectiveAspectJAdvisorFactory.getAdvisors
public List<Advisor> getAdvisors(MetadataAwareAspectInstanceFactory aspectInstanceFactory) {
Class<?> aspectClass = aspectInstanceFactory.getAspectMetadata().getAspectClass();
String aspectName = aspectInstanceFactory.getAspectMetadata().getAspectName();
validate(aspectClass);
MetadataAwareAspectInstanceFactory lazySingletonAspectInstanceFactory =
new LazySingletonAspectInstanceFactoryDecorator(aspectInstanceFactory); // #1
List<Advisor> advisors = new LinkedList<Advisor>();
for (Method method : getAdvisorMethods(aspectClass)) { // #2
Advisor advisor = getAdvisor(method, lazySingletonAspectInstanceFactory, advisors.size(), aspectName); // #3
if (advisor != null) {
advisors.add(advisor);
}
}
...
return advisors;
}
複製代碼
#1
lazySingletonAspectInstanceFactory對getAspectInstance進行了緩存,保證getAspectInstance方法返回單例
#2
getAdvisorMethods獲取全部沒有Pointcut註解的方法(有Pointcut註解的方法不多是Advisor)
#3
使用方法元數據構造單元切面
public Advisor getAdvisor(Method candidateAdviceMethod, MetadataAwareAspectInstanceFactory aspectInstanceFactory,
int declarationOrderInAspect, String aspectName) {
validate(aspectInstanceFactory.getAspectMetadata().getAspectClass());
AspectJExpressionPointcut expressionPointcut = getPointcut(
candidateAdviceMethod, aspectInstanceFactory.getAspectMetadata().getAspectClass()); // #1
if (expressionPointcut == null) {
return null;
}
return new InstantiationModelAwarePointcutAdvisorImpl(expressionPointcut, candidateAdviceMethod,
this, aspectInstanceFactory, declarationOrderInAspect, aspectName); // #2
}
複製代碼
#1
獲取切入點Pointcut,並構建了AspectJExpressionPointcut
#2
建立單元切面InstantiationModelAwarePointcutAdvisorImpl,該類中包含屬性 -- 被攔截類declaringClass,被攔截方法aspectJAdviceMethod,切入點declaredPointcut和通知instantiatedAdvice。
InstantiationModelAwarePointcutAdvisorImpl#構造方法 -> InstantiationModelAwarePointcutAdvisorImpl#instantiateAdvice -> ReflectiveAspectJAdvisorFactory#getAdvice
public Advice getAdvice(Method candidateAdviceMethod, AspectJExpressionPointcut expressionPointcut,
MetadataAwareAspectInstanceFactory aspectInstanceFactory, int declarationOrder, String aspectName) {
... // #1
AbstractAspectJAdvice springAdvice;
switch (aspectJAnnotation.getAnnotationType()) { // #2
case AtBefore:
springAdvice = new AspectJMethodBeforeAdvice(
candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
break;
case AtAfter:
springAdvice = new AspectJAfterAdvice(
candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
break;
case AtAfterReturning:
springAdvice = new AspectJAfterReturningAdvice(
candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
AfterReturning afterReturningAnnotation = (AfterReturning) aspectJAnnotation.getAnnotation();
if (StringUtils.hasText(afterReturningAnnotation.returning())) {
springAdvice.setReturningName(afterReturningAnnotation.returning());
}
break;
case AtAfterThrowing:
springAdvice = new AspectJAfterThrowingAdvice(
candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
AfterThrowing afterThrowingAnnotation = (AfterThrowing) aspectJAnnotation.getAnnotation();
if (StringUtils.hasText(afterThrowingAnnotation.throwing())) {
springAdvice.setThrowingName(afterThrowingAnnotation.throwing());
}
break;
case AtAround:
springAdvice = new AspectJAroundAdvice(
candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
break;
case AtPointcut:
if (logger.isDebugEnabled()) {
logger.debug("Processing pointcut '" + candidateAdviceMethod.getName() + "'");
}
return null;
default:
throw new UnsupportedOperationException(
"Unsupported advice type on method: " + candidateAdviceMethod);
}
// Now to configure the advice...
springAdvice.setAspectName(aspectName);
springAdvice.setDeclarationOrder(declarationOrder);
String[] argNames = this.parameterNameDiscoverer.getParameterNames(candidateAdviceMethod);
if (argNames != null) {
springAdvice.setArgumentNamesFromStringArray(argNames);
}
springAdvice.calculateArgumentBindings();
return springAdvice;
}
複製代碼
#1
aspectInstanceFactory#getAspectMetadata獲取切面信息,再獲取對應的aspectJAnnotation
#2
根據切面類型,構建不一樣的通知實現類
@After對應AspectJAfterAdvice
@Around對應AspectJAroundAdvice
@Before對應AspectJMethodBeforeAdvice
@AfterReturning對應AspectJAfterReturningAdvice
@AfterThrowing對應AspectJAfterThrowingAdvice
除了AspectJAroundAdvice,這些通知實現類都實現了MethodInterceptor(方法攔截器接口)。
這裏會遍歷全部的單元切面,檢查bean的class和class中是否有方法能夠匹配對應的單元切面,若是沒有則過濾該單元切面。代碼比較繁瑣,不展開了。
AspectJAwareAdvisorAutoProxyCreator.extendAdvisors -> AspectJProxyUtils.makeAdvisorChainAspectJCapableIfNecessary
spring會在advisors列表開始位置添加ExposeInvocationInterceptor。 ExposeInvocationInterceptor是一個特殊的MethodInterceptor,它將當前方法攔截器調用鏈放置到線程上下文中,以便有須要時使用。
咱們知道,spring經過動態代理類實現aop,有jdk動態代理和cglib兩種方法。
若是要使用jdk動態代理,被代理類必須實現一個接口。
這裏只關注jdk動態代理如何實現aop。
AbstractAutoProxyCreator#wrapIfNecessary方法#2
步驟 -> AbstractAutoProxyCreator.createProxy(第三個參數就是Advices)
protected Object createProxy( Class<?> beanClass, String beanName, Object[] specificInterceptors, TargetSource targetSource) {
...
Advisor[] advisors = buildAdvisors(beanName, specificInterceptors); // #1
for (Advisor advisor : advisors) {
proxyFactory.addAdvisor(advisor); // #2
}
proxyFactory.setTargetSource(targetSource);
customizeProxyFactory(proxyFactory);
proxyFactory.setFrozen(this.freezeProxy);
if (advisorsPreFiltered()) {
proxyFactory.setPreFiltered(true);
}
return proxyFactory.getProxy(getProxyClassLoader()); // #3
}
複製代碼
#1
類型檢查及轉化,如將Advices轉換成Advisor
#2
將Advisor添加到proxyFactory中
#3
構造代理對象
proxyFactory.getProxy -> ProxyCreatorSupport.createAopProxy
protected final synchronized AopProxy createAopProxy() {
if (!this.active) {
activate();
}
return getAopProxyFactory().createAopProxy(this); // #1
}
複製代碼
#1
構造代理對象,createAopProxy方法參數是this,將proxyFactory將自身做爲參數,
DefaultAopProxyFactory#createAopProxy
public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
if (config.isOptimize() || config.isProxyTargetClass() || hasNoUserSuppliedProxyInterfaces(config)) { // #1
Class<?> targetClass = config.getTargetClass();
if (targetClass == null) {
throw new AopConfigException("TargetSource cannot determine target class: " +
"Either an interface or a target is required for proxy creation.");
}
if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) {
return new JdkDynamicAopProxy(config);
}
return new ObjenesisCglibAopProxy(config);
}
else { // #2
return new JdkDynamicAopProxy(config);
}
}
複製代碼
#1
根據用戶配置和目標bean是否有實現接口,判斷是否須要使用ObjenesisCglibAopProxy #2
使用JDK動態代理
來看看JdkDynamicAopProxy#getProxy
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, true);
findDefinedEqualsAndHashCodeMethods(proxiedInterfaces);
return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this); // #1
}
複製代碼
#1
這裏構造了jdk的動態代理對象,注意newProxyInstance方法第三個參數是this,即JdkDynamicAopProxy,JdkDynamicAopProxy實現了InvocationHandler。
Spring AOP源碼解析內容過長,關於多個通知鏈式調用的解析留到下一篇文章解析
若是您以爲本文不錯,歡迎關注個人微信公衆號,您的關注是我堅持的動力!