導(dǎo)讀
本篇主要針對(duì)spring aop進(jìn)行源碼級(jí)解說派昧,如有不不到位的地方敬請(qǐng)指出,多謝……
本文大綱如下
- spring aop 使用姿勢(shì)
- spring aop 主鏈路概覽
- spring aop 相關(guān)概念
- spring aop 源碼解讀
4.1 編程方式解讀
4.2 配置方式解讀
4.3 注解方式解讀 - spring aop不生效的探索
一拢切、Spring AOP 使用姿勢(shì)
待被加強(qiáng)的目標(biāo)類
public interface Sleepable {
void sleep();
void sleep2();
}
public class SleepableImpl implements Sleepable {
@Override
public void sleep() {
System.out.println("睡覺斗锭!不休息哪里有力氣學(xué)習(xí)!");
this.sleep2();
}
@Override
public void sleep2() {
System.out.println("lalala");
}
}
<!-- 定義被代理者 -->
<bean id="sleepable" class="com.youzan.study.spring.aop.SleepableImpl"/>
1.1 編程式
Advice
public class SleepAdvice2 implements MethodBeforeAdvice, AfterReturningAdvice {
public void before(Method arg0, Object[] arg1, Object arg2) throws Throwable {
System.out.println("睡覺前要脫衣服失球!");
}
public void afterReturning(Object arg0, Method arg1, Object[] arg2, Object arg3) throws Throwable {
System.out.println("起床后要穿衣服!");
}
}
<!--<!–<!–<!– 定義通知內(nèi)容帮毁,也就是切入點(diǎn)執(zhí)行前后需要做的事情 –>–>–>-->
<bean id="sleepAdvice2" class="com.youzan.study.spring.aop.SleepAdvice2"/>
<!-- 定義切入點(diǎn)位置 -->
<bean id="sleepPointcut" class="org.springframework.aop.support.JdkRegexpMethodPointcut">
<property name="pattern" value=".*sleep"/>
</bean>
<!-- 使切入點(diǎn)與通知相關(guān)聯(lián)实苞,完成切面配置 -->
<bean id="sleepHelperAdvisor" class="org.springframework.aop.support.DefaultPointcutAdvisor">
<property name="advice" ref="sleepAdvice2"/>
<property name="pointcut" ref="sleepPointcut"/>
</bean>
<!--編程方式啟用 AOP-->
<bean id="sleepableProxy" class="org.springframework.aop.framework.ProxyFactoryBean">
<!-- 代理的對(duì)象,有睡覺能力 -->
<property name="target" ref="sleepable"/>
<!-- 使用切面 -->
<property name="interceptorNames" value="sleepHelperAdvisor"/>
<!-- 代理接口烈疚,睡覺接口 -->
<property name="proxyInterfaces" value="com.youzan.study.spring.aop.Sleepable"/>
</bean>
調(diào)用姿勢(shì)
FileSystemXmlApplicationContext context = new FileSystemXmlApplicationContext("/"+"配置文件地址");
Sleepable sleepable = (Sleepable)context.getBean("sleepableProxy");
sleepable.sleep();
1.2 配置方式
advice同配置方式一致
<!--<!–<!–<!– 定義通知內(nèi)容黔牵,也就是切入點(diǎn)執(zhí)行前后需要做的事情 –>–>–>-->
<bean id="sleepAdvice2" class="com.youzan.study.spring.aop.SleepAdvice2"/>
<!-- 定義切入點(diǎn)位置 -->
<bean id="sleepPointcut" class="org.springframework.aop.support.JdkRegexpMethodPointcut">
<property name="pattern" value=".*sleep"/>
</bean>
<!-- 使切入點(diǎn)與通知相關(guān)聯(lián),完成切面配置 -->
<bean id="sleepHelperAdvisor" class="org.springframework.aop.support.DefaultPointcutAdvisor">
<property name="advice" ref="sleepAdvice2"/>
<property name="pointcut" ref="sleepPointcut"/>
</bean>
<!--配置的形式啟用 AOP-->
<bean class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator" />
調(diào)用姿勢(shì)
Sleepable sleepable = (Sleepable)context.getBean("sleepable");
sleepable.sleep();
1.3 注解方式
Advice
@Aspect
public class SleepAdvice{
public SleepAdvice(){
}
@Pointcut("execution(* *.sleep*())")
public void sleeppoint(){}
@Before("sleeppoint()")
public void beforeSleep(){
System.out.println("睡覺前要脫衣服!");
}
@AfterReturning("sleeppoint()")
public void afterSleep(){
System.out.println("睡醒了要穿衣服爷肝!");
}
@Around("sleeppoint()")
public void aroundLala(ProceedingJoinPoint pjp) throws Throwable {
System.out.println("快點(diǎn)睡覺;帧!灯抛!");
pjp.proceed();
System.out.println("睡著了=鹕狻!对嚼!");
}
}
<!--注解的形式啟用 AOP-->
<aop:aspectj-autoproxy proxy-target-class="false"/>
<!--<!–定義通知內(nèi)容夹抗,也就是切入點(diǎn)執(zhí)行前后需要做的事情–>-->
<bean id="sleepAdvice" class="com.youzan.study.spring.aop.SleepAdvice"/>
這里先留一個(gè)問題,針對(duì)注解方式纵竖,我們的輸出文本順序是什么漠烧?本文結(jié)束的時(shí)候有答案杏愤,讀者可先自己嘗試思考一下。
調(diào)用姿勢(shì)和配置的方式一樣
二已脓、Spring AOP主鏈路概覽
注解方式和配置方式屬于同類珊楼,基于BeanPostProcessor,在被加強(qiáng)類完成實(shí)例化之后通過BeanPostProcessor進(jìn)行加強(qiáng)度液。
DefaultAdvisorAutoProxyCreator 和 AnnotationAwareAspectJAutoProxyCreator 都屬于BeanPostProcessor厕宗,我們看下他們的類圖
三、核心概念
pointCut
切入點(diǎn)恨诱,對(duì)什么進(jìn)行加強(qiáng)
advice
如何增強(qiáng)媳瞪,是具體的增強(qiáng)動(dòng)作
advisor
通知器,集成 pointCut和advice
spring aop主要有兩種實(shí)現(xiàn)方式照宝,一種是jdk的動(dòng)態(tài)代理蛇受,另一種是基于cglib。
四厕鹃、源碼解讀
4.1 編程方式
容器啟動(dòng)的時(shí)候兢仰,會(huì)將ProxyFactoryBean的實(shí)例創(chuàng)建完畢
獲取代理對(duì)象
當(dāng)我們調(diào)用的時(shí)候
Sleepable sleepable = (Sleepable)context.getBean("sleepableProxy");
spring容器判斷ProxyFactoryBean是否創(chuàng)建完畢,如果創(chuàng)建完畢判斷是否是FacotryBean類型剂碴,如果是的話調(diào)用 ProxyFactoryBean.getObject()把将,這塊可以參考IOC容器部分內(nèi)容,本章節(jié)不細(xì)講
下面看下ProxyFactoryBean如何getObject()
//ProxyFactoryBean
public Object getObject() throws BeansException {
//初始化Advisor chain
initializeAdvisorChain();
if (isSingleton()) {
//獲取或創(chuàng)建proxy 代理對(duì)象
return getSingletonInstance();
}
else {
if (this.targetName == null) {
logger.warn("Using non-singleton proxies with singleton targets is often undesirable. " +
"Enable prototype proxies by setting the 'targetName' property.");
}
return newPrototypeInstance();
}
}
- Advisor chain初始化
private synchronized void initializeAdvisorChain() throws AopConfigException, BeansException {
//是否已初始化
if (this.advisorChainInitialized) {
return;
}
//interceptorNames 就是spring里配置的advisor
if (!ObjectUtils.isEmpty(this.interceptorNames)) {
//省略部分代碼
// Materialize interceptor chain from bean names.
for (String name : this.interceptorNames) {
//省略部分代碼
else {
// If we get here, we need to add a named interceptor.
// We must check if it's a singleton or prototype.
Object advice;
if (this.singleton || this.beanFactory.isSingleton(name)) {
//從spring容器獲取 advisor對(duì)象
advice = this.beanFactory.getBean(name);
}
else {
// 非單例場(chǎng)景下創(chuàng)建 advisor對(duì)象
advice = new PrototypePlaceholderAdvisor(name);
}
//將advisor加入鏈中
addAdvisorOnChainCreation(advice, name);
}
}
}
this.advisorChainInitialized = true;
}
調(diào)用鏈路
|--ProxyFactoryBean.initializeAdvisorChain
|----ProxyFactoryBean.addAdvisorOnChainCreation
|------AdvisedSupport.addAdvisor
|--------AdvisedSupport.addAdvisorInternal
最后會(huì)把a(bǔ)dvisor加入到 ProxyFactoryBean的 advisors
(父類AdvisedSupport的屬性 )里面忆矛,advisor的順序由用戶在spring里的配置決定察蹲。
- 創(chuàng)建Proxy對(duì)象
調(diào)用鏈路
|--ProxyFactoryBean.getObject
|----ProxyFactoryBean.getSingletonInstance
|------ProxyFactoryBean.createAopProxy
|--------ProxyCreatorSupport.createAopProxy
|----------DefaultAopProxyFactory.createAopProxy
|------ProxyFactoryBean.getProxy
|--------JdkDynamicAopProxy.getProxy (或CglibAopProxy)
如何決策使用jdk還是cglib?
//DefaultAopProxyFactory
public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
//根據(jù) proxytargetclass或者 optimize 的配置,或者是否有接口來決策使用jdk動(dòng)態(tài)代理或者cglib
if (config.isOptimize() || config.isProxyTargetClass() || hasNoUserSuppliedProxyInterfaces(config)) {
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()) {
return new JdkDynamicAopProxy(config);
}
return CglibProxyFactory.createCglibProxy(config);
}
else {
return new JdkDynamicAopProxy(config);
}
}
<!--編程方式啟用 AOP-->
<bean id="sleepableProxy" class="org.springframework.aop.framework.ProxyFactoryBean">
<!-- 代理的對(duì)象催训,有睡覺能力 -->
<property name="target" ref="sleepable"/>
<!-- 使用切面 -->
<property name="interceptorNames" value="sleepHelperAdvisor"/>
<!-- 代理接口洽议,睡覺接口 -->
<property name="proxyInterfaces" value="com.youzan.study.spring.aop.Sleepable"/>
<!--指定使用cglib-->
<property name="optimize" value="true" />
</bean>
proxy對(duì)象的創(chuàng)建和調(diào)用,放到下面公共部分解讀
4.2 配置方式
相對(duì)于編程式的區(qū)別漫拭,就是不需要特意指定advisor和待加強(qiáng)對(duì)象之前的關(guān)系亚兄。
該方式的使用需要配置一個(gè)BeanPostProcessor即DefaultAdvisorAutoProxyCreator,當(dāng)待加強(qiáng)類Bean實(shí)例化后會(huì)進(jìn)行BeanPostProcessor的加強(qiáng)采驻。
- 加強(qiáng)的入口
AbstractAutowireCapableBeanFactory#initializeBean
protected Object initializeBean(final String beanName, final Object bean, RootBeanDefinition mbd) {
//省略部分代碼
Object wrappedBean = bean;
if (mbd == null || !mbd.isSynthetic()) {
//BeanPostProcessor 加強(qiáng)
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()) {
//BeanPostProcessor 加強(qiáng),DefaultAdvisorAutoProxyCreator在這里開始介入
wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
}
return wrappedBean;
}
- 獲取加強(qiáng)proxy鏈路
|--AbstractAutowireCapableBeanFactory.
applyBeanPostProcessorsAfterInitialization
|----AbstractAutoProxyCreator.postProcessAfterInitialization
|------AbstractAutoProxyCreator.wrapIfNecessary
|--------AbstractAutoProxyCreator.getAdvicesAndAdvisorsForBean
|--------AbstractAutoProxyCreator.createProxy
|----------ProxyFactory.getProxy
|------------DefaultAopProxyFactory.createAopProxy
|--------------JdkDynamicAopProxy.getProxy (或CglibAopProxy)
AbstractAutoProxyCreator.getAdvicesAndAdvisorsForBean 如何尋找待加強(qiáng)類對(duì)應(yīng)的advisors呢审胚?
//AbstractAdvisorAutoProxyCreator
protected List<Advisor> findEligibleAdvisors(Class beanClass, String beanName) {
//獲取當(dāng)前容器所有的advisors,根據(jù)Advisor接口類型進(jìn)行查找
List<Advisor> candidateAdvisors = findCandidateAdvisors();
//獲取適合當(dāng)前容器的advisors
List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);
extendAdvisors(eligibleAdvisors);
if (!eligibleAdvisors.isEmpty()) {
//對(duì)advisor進(jìn)行排序
eligibleAdvisors = sortAdvisors(eligibleAdvisors);
}
return eligibleAdvisors;
}
- advisor的排序礼旅,為什么要排序呢膳叨?如果待加強(qiáng)類適配的不僅僅一個(gè)advisor,那么誰先誰后呢痘系?這基于OrderComparator進(jìn)行排序,而它的實(shí)現(xiàn)邏輯也是基于advisor的order來的懒鉴。
public int compare(Object o1, Object o2) {
boolean p1 = (o1 instanceof PriorityOrdered);
boolean p2 = (o2 instanceof PriorityOrdered);
if (p1 && !p2) {
return -1;
}
else if (p2 && !p1) {
return 1;
}
// Direct evaluation instead of Integer.compareTo to avoid unnecessary object creation.
int i1 = getOrder(o1);
int i2 = getOrder(o2);
return (i1 < i2) ? -1 : (i1 > i2) ? 1 : 0;
}
- 查找匹配的advisors
//AbstractAdvisorAutoProxyCreator
protected List<Advisor> findAdvisorsThatCanApply(
List<Advisor> candidateAdvisors, Class beanClass, String beanName) {
ProxyCreationContext.setCurrentProxiedBeanName(beanName);
try {
//尋找匹配當(dāng)前類的advisor
return AopUtils.findAdvisorsThatCanApply(candidateAdvisors, beanClass);
}
finally {
ProxyCreationContext.setCurrentProxiedBeanName(null);
}
}
//真正的匹配邏輯 在 AopUtils
public static boolean canApply(Pointcut pc, Class<?> targetClass, boolean hasIntroductions) {
Assert.notNull(pc, "Pointcut must not be null");
//判斷類是否匹配
if (!pc.getClassFilter().matches(targetClass)) {
return false;
}
//獲取pointcut 的方法匹配器
MethodMatcher methodMatcher = pc.getMethodMatcher();
IntroductionAwareMethodMatcher introductionAwareMethodMatcher = null;
if (methodMatcher instanceof IntroductionAwareMethodMatcher) {
introductionAwareMethodMatcher = (IntroductionAwareMethodMatcher) methodMatcher;
}
Set<Class> classes = new LinkedHashSet<Class>(ClassUtils.getAllInterfacesForClassAsSet(targetClass));
classes.add(targetClass);
for (Class<?> clazz : classes) {
//讀取待加強(qiáng)類所有的方法,查看是否有匹配上的
Method[] methods = clazz.getMethods();
for (Method method : methods) {
if ((introductionAwareMethodMatcher != null &&
introductionAwareMethodMatcher.matches(method, targetClass, hasIntroductions)) ||
methodMatcher.matches(method, targetClass)) {
return true;
}
}
}
return false;
}
如果沒有找到匹配的advisor,那么認(rèn)為該類不需要加強(qiáng)临谱,直接返回原生的bean實(shí)例璃俗,反之走創(chuàng)建proxy的鏈路。
//AbstractAutoProxyCreator
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;
}
//判斷如果是advisor或者advice類就加入到advisedBeans中悉默,value=false城豁,表示這些bean不需要進(jìn)行proxy后續(xù)邏輯
if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) {
this.advisedBeans.put(cacheKey, Boolean.FALSE);
return bean;
}
//查找是否有匹配的advisor
Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
if (specificInterceptors != DO_NOT_PROXY) {
this.advisedBeans.put(cacheKey, Boolean.TRUE);
//創(chuàng)建 proxy對(duì)象
Object proxy = createProxy(bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
this.proxyTypes.put(cacheKey, proxy.getClass());
return proxy;
}
//標(biāo)記該類不需要加強(qiáng),并返回普通的bean實(shí)例
this.advisedBeans.put(cacheKey, Boolean.FALSE);
return bean;
}
4.3 注解方式
注解方式相比前兩種方式更為輕量抄课,注解方式和配置方式相比編程方式對(duì)待加強(qiáng)類零侵入唱星、零耦合。
注解方式原理與配置方式類似跟磨,都是基于BeanPostProcessor進(jìn)行bean實(shí)例加強(qiáng)间聊。但是不同的是注解方式由spring aop模塊自動(dòng)向容器加入AnnotationAwareAspectJAutoProxyCreator
BeanPostProcessor ,另外advisor也是程序基于代碼注解自動(dòng)提取和組裝抵拘。
使用注解
<aop:aspectj-autoproxy proxy-target-class="false"/>
相比<bean>標(biāo)簽哎榴,對(duì)應(yīng)的解析類也是不一樣的。spring aop模塊下的spring.handlers 里指定 解析類 AopNamespaceHandler
//AopNamespaceHandler
public void init() {
// In 2.0 XSD as well as in 2.1 XSD.
registerBeanDefinitionParser("config", new ConfigBeanDefinitionParser());
registerBeanDefinitionParser("aspectj-autoproxy", new AspectJAutoProxyBeanDefinitionParser());
registerBeanDefinitionDecorator("scoped-proxy", new ScopedProxyBeanDefinitionDecorator());
// Only in 2.0 XSD: moved to context namespace as of 2.1
registerBeanDefinitionParser("spring-configured", new SpringConfiguredBeanDefinitionParser());
}
我們使用的 aspectj-autoproxy
剛好對(duì)應(yīng) AspectJAutoProxyBeanDefinitionParser僵蛛。
容器注冊(cè)AnnotationAwareAspectJAutoProxyCreator BeanPostProcessor
//AspectJAutoProxyBeanDefinitionParser
public BeanDefinition parse(Element element, ParserContext parserContext) {
//注冊(cè) AspectJAnnotationAutoProxyCreator
AopNamespaceUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(parserContext, element);
//如果有子節(jié)點(diǎn)進(jìn)行子節(jié)點(diǎn)處理尚蝌,暫未用到,暫時(shí)忽略
extendBeanDefinition(element, parserContext);
return null;
}
//AopNamespaceUtils
public static void registerAspectJAnnotationAutoProxyCreatorIfNecessary(
ParserContext parserContext, Element sourceElement) {
//生成AspectJAnnotationAutoProxyCreator 的beanDefinition信息并注冊(cè)到容器中充尉,
//name=org.springframework.aop.config.internalAutoProxyCreator
BeanDefinition beanDefinition = AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(
parserContext.getRegistry(), parserContext.extractSource(sourceElement));
//對(duì) aspectj-autoproxy 的屬性進(jìn)行組裝飘言,比如proxy-target-class
useClassProxyingIfNecessary(parserContext.getRegistry(), sourceElement);
registerComponentIfNecessary(beanDefinition, parserContext);
}
接著在容器啟動(dòng)的過程中 registerBeanPostProcessors() 進(jìn)行實(shí)例化。
提取advisors
獲取加強(qiáng)proxy鏈路和配置方式一致驼侠,不同的在于注解方式獲取advisors是代碼自動(dòng)提取的姿鸿,AnnotationAwareAspectJAutoProxyCreator把AbstractAdvisorAutoProxyCreator的findCandidateAdvisors
覆蓋了,有了自己的實(shí)現(xiàn)邏輯
//AnnotationAwareAspectJAutoProxyCreator
protected List<Advisor> findCandidateAdvisors() {
//調(diào)用父類的方法倒源,檢索容器中所有的advisor
List<Advisor> advisors = super.findCandidateAdvisors();
//構(gòu)建加AspectJ注解的advisor
advisors.addAll(this.aspectJAdvisorsBuilder.buildAspectJAdvisors());
return advisors;
}
根據(jù)加@Aspect注解的bean生成advisors的調(diào)用鏈路
|--BeanFactoryAspectJAdvisorsBuilder.buildAspectJAdvisors
|----ReflectiveAspectJAdvisorFactory.getAdvisors
|------ReflectiveAspectJAdvisorFactory.getAdvisor
|--------new InstantiationModelAwarePointcutAdvisorImpl()
|----------InstantiationModelAwarePointcutAdvisorImpl.instantiateAdvice
|------------ReflectiveAspectJAdvisorFactory.getAdvice
//BeanFactoryAspectJAdvisorsBuilder
public List<Advisor> buildAspectJAdvisors() {
List<String> aspectNames = null;
//省略一大段代碼苛预,代碼篇幅較長(zhǎng),可以認(rèn)為 它把spring容器中的bean都拿了出來相速,
//然后判斷是否添加了 @Aspect 注解
//根據(jù)提取出來的 @Aspect 進(jìn)行進(jìn)一步的組裝,獲取到具體的Advisor并添加到 advisors中返回
List<Advisor> advisors = new LinkedList<Advisor>();
for (String aspectName : aspectNames) {
//從緩存中讀取已經(jīng)生成的 advisors
List<Advisor> cachedAdvisors = this.advisorsCache.get(aspectName);
if (cachedAdvisors != null) {
advisors.addAll(cachedAdvisors);
}
else {
MetadataAwareAspectInstanceFactory factory = this.aspectFactoryCache.get(aspectName);
//具體生成advisors 的邏輯
advisors.addAll(this.advisorFactory.getAdvisors(factory));
}
}
return advisors;
}
//ReflectiveAspectJAdvisorFactory
public List<Advisor> getAdvisors(MetadataAwareAspectInstanceFactory maaif) {
final Class<?> aspectClass = maaif.getAspectMetadata().getAspectClass();
final String aspectName = maaif.getAspectMetadata().getAspectName();
validate(aspectClass);
final MetadataAwareAspectInstanceFactory lazySingletonAspectInstanceFactory =
new LazySingletonAspectInstanceFactoryDecorator(maaif);
final List<Advisor> advisors = new LinkedList<Advisor>();
//getAdvisorMethods(aspectClass) 會(huì)找到所有加注解的方法
for (Method method : getAdvisorMethods(aspectClass)) {
Advisor advisor = getAdvisor(method, lazySingletonAspectInstanceFactory, advisors.size(), aspectName);
if (advisor != null) {
advisors.add(advisor);
}
}
// 省略部分代碼鲜锚,平時(shí)沒有用到這些場(chǎng)景突诬,這里就不解讀了
return advisors;
}
getAdvisorMethods方法,會(huì)把所有帶有注解的方法給提取出來芜繁,提取后會(huì)對(duì)方法進(jìn)行排序旺隙,因?yàn)樵诤竺嬖O(shè)置advice order的時(shí)候有一個(gè)聲明順序,會(huì)起到一定的優(yōu)先級(jí)影響骏令。
//ReflectiveAspectJAdvisorFactory
private List<Method> getAdvisorMethods(Class<?> aspectClass) {
final List<Method> methods = new LinkedList<Method>();
ReflectionUtils.doWithMethods(aspectClass, new ReflectionUtils.MethodCallback() {
public void doWith(Method method) throws IllegalArgumentException {
// Exclude pointcuts
if (AnnotationUtils.getAnnotation(method, Pointcut.class) == null) {
methods.add(method);
}
}
});
//對(duì)方法進(jìn)行排序
Collections.sort(methods, METHOD_COMPARATOR);
return methods;
}
方法的排序規(guī)則
Around.class, Before.class, After.class, AfterReturning.class, AfterThrowing.class
按照上面的注解順序進(jìn)行排序蔬捷,如果不屬于上面的注解類型,排序統(tǒng)一為方法總數(shù)量。
ReflectiveAspectJAdvisorFactory.getAdvisor
public Advisor getAdvisor(Method candidateAdviceMethod, MetadataAwareAspectInstanceFactory aif,
int declarationOrderInAspect, String aspectName) {
validate(aif.getAspectMetadata().getAspectClass());
//提取 pointcut周拐,如果為空則返回null
AspectJExpressionPointcut ajexp =
getPointcut(candidateAdviceMethod, aif.getAspectMetadata().getAspectClass());
if (ajexp == null) {
return null;
}
//生成InstantiationModelAwarePointcutAdvisorImpl advisor铡俐,
//advice=aif(可以認(rèn)為是當(dāng)前加了@Aspect的advice類), pointcut 就是根據(jù)注解提取出來的
return new InstantiationModelAwarePointcutAdvisorImpl(
this, ajexp, aif, candidateAdviceMethod, declarationOrderInAspect, aspectName);
}
getAdvice的邏輯
//ReflectiveAspectJAdvisorFactory
public Advice getAdvice(Method candidateAdviceMethod, AspectJExpressionPointcut ajexp,
MetadataAwareAspectInstanceFactory aif, int declarationOrderInAspect, String aspectName) {
Class<?> candidateAspectClass = aif.getAspectMetadata().getAspectClass();
validate(candidateAspectClass);
//獲取當(dāng)前方法注解
AspectJAnnotation<?> aspectJAnnotation =
AbstractAspectJAdvisorFactory.findAspectJAnnotationOnMethod(candidateAdviceMethod);
if (aspectJAnnotation == null) {
return null;
}
// Check 是否是 AspectJ-annotated class
if (!isAspect(candidateAspectClass)) {
throw new AopConfigException("Advice must be declared inside an aspect type: " +
"Offending method '" + candidateAdviceMethod + "' in class [" +
candidateAspectClass.getName() + "]");
}
//省略部分代碼
AbstractAspectJAdvice springAdvice;
//不同的注解類型,不同的advice
switch (aspectJAnnotation.getAnnotationType()) {
case AtBefore:
springAdvice = new AspectJMethodBeforeAdvice(candidateAdviceMethod, ajexp, aif);
break;
case AtAfter:
springAdvice = new AspectJAfterAdvice(candidateAdviceMethod, ajexp, aif);
break;
case AtAfterReturning:
springAdvice = new AspectJAfterReturningAdvice(candidateAdviceMethod, ajexp, aif);
//省略部分代碼
break;
case AtAfterThrowing:
springAdvice = new AspectJAfterThrowingAdvice(candidateAdviceMethod, ajexp, aif);
AfterThrowing afterThrowingAnnotation = (AfterThrowing) aspectJAnnotation.getAnnotation();
//省略部分代碼
break;
case AtAround:
springAdvice = new AspectJAroundAdvice(candidateAdviceMethod, ajexp, aif);
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);
//設(shè)置advice的 聲明順序妥粟,當(dāng)advice order 順序一樣的時(shí)候审丘,該排序會(huì)有一定的影響
springAdvice.setDeclarationOrder(declarationOrderInAspect);
String[] argNames = this.parameterNameDiscoverer.getParameterNames(candidateAdviceMethod);
if (argNames != null) {
springAdvice.setArgumentNamesFromStringArray(argNames);
}
springAdvice.calculateArgumentBindings();
return springAdvice;
}
幾個(gè)advice類型的類圖我們看下
Advisor 優(yōu)先級(jí)
Advisor的優(yōu)先級(jí)邏輯,配置方式和注解方式一致勾给。
我們的advisor已經(jīng)生成完畢滩报,advisor的優(yōu)先級(jí)排序邏輯入口在AspectJAwareAdvisorAutoProxyCreator.sortAdvisors捞高。
Advisor排序鏈路
|--AspectJAwareAdvisorAutoProxyCreator.sortAdvisors
|----PartialOrder.sort
|------PartialOrder.addNewPartialComparable
|--------PartialOrder.addDirectedLinks
|----------AspectJPrecedenceComparator.compare
|------------AspectJPrecedenceComparator.comparePrecedenceWithinAspect
排序中最為關(guān)鍵的點(diǎn)
PartialOrder.addNewPartialComparable 這一步夭委,將待排序的對(duì)象包裝成PartialOrder.SortObject對(duì)象灌危,這個(gè)對(duì)象有三個(gè)屬性
//advisor holder
PartialComparable object;
//比當(dāng)前advisor order 小的Advisors
List<SortObject> smallerObjects = new LinkedList<SortObject>();
//比當(dāng)前advisor order 大的Advisors
List<SortObject> biggerObjects = new LinkedList<SortObject>();
PartialOrder.sort就是針對(duì)上面處理之后的SortObjects進(jìn)行排序沛膳。
排序規(guī)則首先獲取Advisor的order裂七,小的優(yōu)先級(jí)最高屏箍,如果order一樣則取 declareOrder也就前面說的聲明順序淤堵,這里需要注意的是瞪浸,聲明順序并發(fā)是和我們代碼里的屬性一致生真,它是經(jīng)過排序的沉噩,排序邏輯向上可以找下。
當(dāng)Advisor的order一樣后柱蟀,排序會(huì)進(jìn)入到下面的邏輯
AspectJPrecedenceComparator.comparePrecedenceWithinAspect
private int comparePrecedenceWithinAspect(Advisor advisor1, Advisor advisor2) {
//兩個(gè)Advisor 是否其中一個(gè)或者全部都是 after類型的Advisor
boolean oneOrOtherIsAfterAdvice =
(AspectJAopUtils.isAfterAdvice(advisor1) || AspectJAopUtils.isAfterAdvice(advisor2));
int adviceDeclarationOrderDelta = getAspectDeclarationOrder(advisor1) - getAspectDeclarationOrder(advisor2);
if (oneOrOtherIsAfterAdvice) {
//如果其中一個(gè)或者全部是 after類型的川蒙,先聲明的優(yōu)先級(jí)反而低
if (adviceDeclarationOrderDelta < 0) {
return LOWER_PRECEDENCE;
}
else if (adviceDeclarationOrderDelta == 0) {
return SAME_PRECEDENCE;
}
else {
return HIGHER_PRECEDENCE;
}
}
else {
//如果不是after類型的,哪個(gè)方法先聲明則擁有更高的優(yōu)先級(jí)长已。
if (adviceDeclarationOrderDelta < 0) {
return HIGHER_PRECEDENCE;
}
else if (adviceDeclarationOrderDelta == 0) {
return SAME_PRECEDENCE;
}
else {
return LOWER_PRECEDENCE;
}
}
}
4.4 proxy調(diào)用解讀
本小節(jié)畜眨,三種aop使用方式的proxy創(chuàng)建和調(diào)用邏輯相同,所以放到一起進(jìn)行講解
創(chuàng)建proxy創(chuàng)建
//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);
//原聲帶jdk創(chuàng)建proxy的api調(diào)用
return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this);
}
使用的是原生的jdk 動(dòng)態(tài)代理api
proxy方法調(diào)用
當(dāng)我們獲得到proxy之后术瓮,然后調(diào)用業(yè)務(wù)方法的時(shí)候康聂,執(zhí)行鏈路最終到了 proxy的invoke方法。
調(diào)用鏈路
|--JdkDynamicAopProxy.invoke
|----AdvisedSupport.getInterceptorsAndDynamicInterceptionAdvice
|------DefaultAdvisorChainFactory.getInterceptorsAndDynamicInterceptionAdvice
|--------MethodBeforeAdviceAdapter.getInterceptor
|--------AfterReturningAdviceAdapter.getInterceptor
|----ReflectiveMethodInvocation.proceed
|------MethodBeforeAdviceInterceptor.invoke
|------AfterReturningAdviceInterceptor.invoke
JdkDynamicAopProxy.invoke方法
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
MethodInvocation invocation;
Object oldProxy = null;
boolean setProxyContext = false;
TargetSource targetSource = this.advised.targetSource;
Class<?> targetClass = null;
Object target = null;
try {
//省略部分代碼
//獲取當(dāng)前執(zhí)行對(duì)象匹配的advice chain
List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
if (chain.isEmpty()) {
//如果chain為空胞四,直接執(zhí)行targetd fangf
retVal = AopUtils.invokeJoinpointUsingReflection(target, method, args);
}
else {
// We need to create a method invocation...
invocation = new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain);
//開始執(zhí)行邏輯恬汁,并返回結(jié)果
retVal = invocation.proceed();
}
//省略部分代碼
return retVal;
}
finally {
if (target != null && !targetSource.isStatic()) {
// Must have come from TargetSource.
targetSource.releaseTarget(target);
}
if (setProxyContext) {
// Restore old proxy.
AopContext.setCurrentProxy(oldProxy);
}
}
}
獲取當(dāng)前方法的advice鏈,邏輯入口
AdvisedSupport.getInterceptorsAndDynamicInterceptionAdvice
具體實(shí)現(xiàn)在DefaultAdvisorChainFactory.getInterceptorsAndDynamicInterceptionAdvice
public List<Object> getInterceptorsAndDynamicInterceptionAdvice(
Advised config, Method method, Class targetClass) {
List<Object> interceptorList = new ArrayList<Object>(config.getAdvisors().length);
boolean hasIntroductions = hasMatchingIntroductions(config, targetClass);
AdvisorAdapterRegistry registry = GlobalAdvisorAdapterRegistry.getInstance();
//循環(huán)當(dāng)前targetClass的advisors
for (Advisor advisor : config.getAdvisors()) {
if (advisor instanceof PointcutAdvisor) {
//獲取當(dāng)前advisor的pointcut
PointcutAdvisor pointcutAdvisor = (PointcutAdvisor) advisor;
if (config.isPreFiltered() || pointcutAdvisor.getPointcut().getClassFilter().matches(targetClass)) {
//根據(jù)advisor獲取interceptors
MethodInterceptor[] interceptors = registry.getInterceptors(advisor);
MethodMatcher mm = pointcutAdvisor.getPointcut().getMethodMatcher();
//判斷當(dāng)前方法是否匹配當(dāng)前advisor的pointcut
if (MethodMatchers.matches(mm, method, targetClass, hasIntroductions)) {
if (mm.isRuntime()) {
for (MethodInterceptor interceptor : interceptors) {
interceptorList.add(new InterceptorAndDynamicMethodMatcher(interceptor, mm));
}
}
else {
//將當(dāng)前advisor對(duì)應(yīng)interceptors 加入到 interceptorList
interceptorList.addAll(Arrays.asList(interceptors));
}
}
}
}else if (advisor instanceof IntroductionAdvisor) {
IntroductionAdvisor ia = (IntroductionAdvisor) advisor;
if (config.isPreFiltered() || ia.getClassFilter().matches(targetClass)) {
Interceptor[] interceptors = registry.getInterceptors(advisor);
interceptorList.addAll(Arrays.asList(interceptors));
}
}
else {
//如果不是上述兩種類型辜伟,則作為Interceptor 直接加入 比如 ExposeInvocationInterceptor
Interceptor[] interceptors = registry.getInterceptors(advisor);
interceptorList.addAll(Arrays.asList(interceptors));
}
}
return interceptorList;
}
如何根據(jù)advisor獲取interceptors 氓侧?
//DefaultAdvisorAdapterRegistry
public MethodInterceptor[] getInterceptors(Advisor advisor) throws UnknownAdviceTypeException {
List<MethodInterceptor> interceptors = new ArrayList<MethodInterceptor>(3);
Advice advice = advisor.getAdvice();
if (advice instanceof MethodInterceptor) {
interceptors.add((MethodInterceptor) advice);
}
for (AdvisorAdapter adapter : this.adapters) {
if (adapter.supportsAdvice(advice)) {
interceptors.add(adapter.getInterceptor(advisor));
}
}
if (interceptors.isEmpty()) {
throw new UnknownAdviceTypeException(advisor.getAdvice());
}
return interceptors.toArray(new MethodInterceptor[interceptors.size()]);
}
adapters 在DefaultAdvisorAdapterRegistry實(shí)例化的時(shí)候完成裝配
public DefaultAdvisorAdapterRegistry() {
registerAdvisorAdapter(new MethodBeforeAdviceAdapter());
registerAdvisorAdapter(new AfterReturningAdviceAdapter());
registerAdvisorAdapter(new ThrowsAdviceAdapter());
}
這些adapters判斷是否支持當(dāng)前advisor的advice,我們以MethodBeforeAdviceAdapter 為例
public boolean supportsAdvice(Advice advice) {
return (advice instanceof MethodBeforeAdvice);
}
getInterceptor邏輯
public MethodInterceptor getInterceptor(Advisor advisor) {
MethodBeforeAdvice advice = (MethodBeforeAdvice) advisor.getAdvice();
return new MethodBeforeAdviceInterceptor(advice);
}
現(xiàn)在我們獲取到了當(dāng)前方法匹配的MethodInterceptor导狡,最后也就是 MethodInterceptor chain约巷。接下來看下具體的執(zhí)行邏輯ReflectiveMethodInvocation.proceed()
public Object proceed() throws Throwable {
//interceptors chain執(zhí)行完畢,則開始執(zhí)行target的method
if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {
return invokeJoinpoint();
}
//MethodInterceptor chain每執(zhí)行一個(gè)旱捧,currentInterceptorIndex + 1
Object interceptorOrInterceptionAdvice =
this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex);
if (interceptorOrInterceptionAdvice instanceof InterceptorAndDynamicMethodMatcher) {
//省略代碼独郎,本篇使用的樣例踩麦,不會(huì)走到該邏輯
}
else {
// 按照 MethodInterceptor chain執(zhí)行邏輯
return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this);
}
}
jdk的動(dòng)態(tài)代理就介紹到這了,cglib方式的先不介紹了氓癌,當(dāng)然本篇也并非面面俱到谓谦,如果有朋友對(duì)本篇沒有提及部分感興趣的話,可以按照這個(gè)思路自己探索一番顽铸。
有興趣的朋友可以自行研究下茁计,這里就不介紹了。
五谓松、Spring AOP 不生效的探索
在使用spring aop的時(shí)候星压,可能我們會(huì)時(shí)不時(shí)的出現(xiàn)aop不生效的問題,最常見的莫過于spring的事務(wù)鬼譬,為什么有時(shí)候不生效呢娜膘?
通過上面的幾個(gè)章節(jié),這個(gè)圖大家不難理解优质,
前提
我們有 method A 和 methodB的兩個(gè)切面
case1:調(diào)用 C.A竣贪, 方法A切面生效
case2: 調(diào)用C.B, 方法B切面生效
case3: 調(diào)用C.A, C.A調(diào)用C.B,方法A切面生效巩螃, 方法B切面失效演怎。
通過圖中表述,當(dāng)方法A切面生效的時(shí)候避乏,調(diào)用到 目標(biāo)類C的B方法爷耀,這時(shí)候調(diào)用B的對(duì)象是目標(biāo)類C而非 代理對(duì)象,所以對(duì)方法B的加強(qiáng)會(huì)不起作用
文章開頭的問題答案如下:
輸出內(nèi)容
快點(diǎn)睡覺E钠ぁ4醵!!
睡覺前要脫衣服!
睡覺铆帽!不休息哪里有力氣學(xué)習(xí)咆耿!
lalala
睡著了!5鳌萨螺!
睡醒了要穿衣服!
系列文章
spring源碼探索(0)-IOC容器-架構(gòu)設(shè)計(jì)
spring源碼探索(1)-IOC容器-Resource
spring源碼探索(2)-IOC容器-BeanDefinition加載與注冊(cè)
spring源碼探索(3)-IOC容器-Bean的一生
spring源碼探索(4)-AOP實(shí)現(xiàn)原理