导读
本篇主要针对spring aop进行源码级解说,如有不不到位的地方敬请指出,多谢……
本文大纲如下
- spring aop 使用姿势
- spring aop 主链路概览
- spring aop 相关概念
- spring aop 源码解读
4.1 编程方式解读
4.2 配置方式解读
4.3 注解方式解读 - spring aop不生效的探索
一、Spring AOP 使用姿势
待被加强的目标类
public interface Sleepable {
void sleep();
void sleep2();
}
public class SleepableImpl implements Sleepable {
@Override
public void sleep() {
System.out.println("睡觉!不休息哪里有力气学习!");
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("起床后要穿衣服!");
}
}
<!--<!–<!–<!– 定义通知内容,也就是切入点执行前后需要做的事情 –>–>–>-->
<bean id="sleepAdvice2" class="com.youzan.study.spring.aop.SleepAdvice2"/>
<!-- 定义切入点位置 -->
<bean id="sleepPointcut" class="org.springframework.aop.support.JdkRegexpMethodPointcut">
<property name="pattern" value=".*sleep"/>
</bean>
<!-- 使切入点与通知相关联,完成切面配置 -->
<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">
<!-- 代理的对象,有睡觉能力 -->
<property name="target" ref="sleepable"/>
<!-- 使用切面 -->
<property name="interceptorNames" value="sleepHelperAdvisor"/>
<!-- 代理接口,睡觉接口 -->
<property name="proxyInterfaces" value="com.youzan.study.spring.aop.Sleepable"/>
</bean>
调用姿势
FileSystemXmlApplicationContext context = new FileSystemXmlApplicationContext("/"+"配置文件地址");
Sleepable sleepable = (Sleepable)context.getBean("sleepableProxy");
sleepable.sleep();
1.2 配置方式
advice同配置方式一致
<!--<!–<!–<!– 定义通知内容,也就是切入点执行前后需要做的事情 –>–>–>-->
<bean id="sleepAdvice2" class="com.youzan.study.spring.aop.SleepAdvice2"/>
<!-- 定义切入点位置 -->
<bean id="sleepPointcut" class="org.springframework.aop.support.JdkRegexpMethodPointcut">
<property name="pattern" value=".*sleep"/>
</bean>
<!-- 使切入点与通知相关联,完成切面配置 -->
<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" />
调用姿势
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("快点睡觉!!!");
pjp.proceed();
System.out.println("睡着了!!!");
}
}
<!--注解的形式启用 AOP-->
<aop:aspectj-autoproxy proxy-target-class="false"/>
<!--<!–定义通知内容,也就是切入点执行前后需要做的事情–>-->
<bean id="sleepAdvice" class="com.youzan.study.spring.aop.SleepAdvice"/>
这里先留一个问题,针对注解方式,我们的输出文本顺序是什么?本文结束的时候有答案,读者可先自己尝试思考一下。
调用姿势和配置的方式一样
二、Spring AOP主链路概览
主要链路注解方式和配置方式属于同类,基于BeanPostProcessor,在被加强类完成实例化之后通过BeanPostProcessor进行加强。
DefaultAdvisorAutoProxyCreator 和 AnnotationAwareAspectJAutoProxyCreator 都属于BeanPostProcessor,我们看下他们的类图
aop BeanPostProcessor类图三、核心概念
pointCut
切入点,对什么进行加强
advice
如何增强,是具体的增强动作
advisor
通知器,集成 pointCut和advice
spring aop主要有两种实现方式,一种是jdk的动态代理,另一种是基于cglib。
四、源码解读
4.1 编程方式
-
容器启动的时候,会将ProxyFactoryBean的实例创建完毕
-
获取代理对象
当我们调用的时候
Sleepable sleepable = (Sleepable)context.getBean("sleepableProxy");
spring容器判断ProxyFactoryBean是否创建完毕,如果创建完毕判断是否是FacotryBean类型,如果是的话调用 ProxyFactoryBean.getObject(),这块可以参考IOC容器部分内容,本章节不细讲
下面看下ProxyFactoryBean如何getObject()
//ProxyFactoryBean
public Object getObject() throws BeansException {
//初始化Advisor chain
initializeAdvisorChain();
if (isSingleton()) {
//获取或创建proxy 代理对象
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对象
advice = this.beanFactory.getBean(name);
}
else {
// 非单例场景下创建 advisor对象
advice = new PrototypePlaceholderAdvisor(name);
}
//将advisor加入链中
addAdvisorOnChainCreation(advice, name);
}
}
}
this.advisorChainInitialized = true;
}
调用链路
|--ProxyFactoryBean.initializeAdvisorChain
|----ProxyFactoryBean.addAdvisorOnChainCreation
|------AdvisedSupport.addAdvisor
|--------AdvisedSupport.addAdvisorInternal
最后会把advisor加入到 ProxyFactoryBean的 advisors
(父类AdvisedSupport的属性 )里面,advisor的顺序由用户在spring里的配置决定。
- 创建Proxy对象
调用链路
|--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 {
//根据 proxytargetclass或者 optimize 的配置,或者是否有接口来决策使用jdk动态代理或者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">
<!-- 代理的对象,有睡觉能力 -->
<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对象的创建和调用,放到下面公共部分解读
4.2 配置方式
相对于编程式的区别,就是不需要特意指定advisor和待加强对象之前的关系。
该方式的使用需要配置一个BeanPostProcessor即DefaultAdvisorAutoProxyCreator,当待加强类Bean实例化后会进行BeanPostProcessor的加强。
- 加强的入口
AbstractAutowireCapableBeanFactory#initializeBean
protected Object initializeBean(final String beanName, final Object bean, RootBeanDefinition mbd) {
//省略部分代码
Object wrappedBean = bean;
if (mbd == null || !mbd.isSynthetic()) {
//BeanPostProcessor 加强
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 加强,DefaultAdvisorAutoProxyCreator在这里开始介入
wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
}
return wrappedBean;
}
- 获取加强proxy链路
|--AbstractAutowireCapableBeanFactory.
applyBeanPostProcessorsAfterInitialization
|----AbstractAutoProxyCreator.postProcessAfterInitialization
|------AbstractAutoProxyCreator.wrapIfNecessary
|--------AbstractAutoProxyCreator.getAdvicesAndAdvisorsForBean
|--------AbstractAutoProxyCreator.createProxy
|----------ProxyFactory.getProxy
|------------DefaultAopProxyFactory.createAopProxy
|--------------JdkDynamicAopProxy.getProxy (或CglibAopProxy)
AbstractAutoProxyCreator.getAdvicesAndAdvisorsForBean 如何寻找待加强类对应的advisors呢?
//AbstractAdvisorAutoProxyCreator
protected List<Advisor> findEligibleAdvisors(Class beanClass, String beanName) {
//获取当前容器所有的advisors,根据Advisor接口类型进行查找
List<Advisor> candidateAdvisors = findCandidateAdvisors();
//获取适合当前容器的advisors
List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);
extendAdvisors(eligibleAdvisors);
if (!eligibleAdvisors.isEmpty()) {
//对advisor进行排序
eligibleAdvisors = sortAdvisors(eligibleAdvisors);
}
return eligibleAdvisors;
}
- advisor的排序,为什么要排序呢?如果待加强类适配的不仅仅一个advisor,那么谁先谁后呢?这基于OrderComparator进行排序,而它的实现逻辑也是基于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 {
//寻找匹配当前类的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) {
//读取待加强类所有的方法,查看是否有匹配上的
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,那么认为该类不需要加强,直接返回原生的bean实例,反之走创建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不需要进行proxy后续逻辑
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);
//创建 proxy对象
Object proxy = createProxy(bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
this.proxyTypes.put(cacheKey, proxy.getClass());
return proxy;
}
//标记该类不需要加强,并返回普通的bean实例
this.advisedBeans.put(cacheKey, Boolean.FALSE);
return bean;
}
4.3 注解方式
注解方式相比前两种方式更为轻量,注解方式和配置方式相比编程方式对待加强类零侵入、零耦合。
注解方式原理与配置方式类似,都是基于BeanPostProcessor进行bean实例加强。但是不同的是注解方式由spring aop模块自动向容器加入AnnotationAwareAspectJAutoProxyCreator
BeanPostProcessor ,另外advisor也是程序基于代码注解自动提取和组装。
使用注解
<aop:aspectj-autoproxy proxy-target-class="false"/>
相比<bean>标签,对应的解析类也是不一样的。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
刚好对应 AspectJAutoProxyBeanDefinitionParser。
容器注册AnnotationAwareAspectJAutoProxyCreator BeanPostProcessor
//AspectJAutoProxyBeanDefinitionParser
public BeanDefinition parse(Element element, ParserContext parserContext) {
//注册 AspectJAnnotationAutoProxyCreator
AopNamespaceUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(parserContext, element);
//如果有子节点进行子节点处理,暂未用到,暂时忽略
extendBeanDefinition(element, parserContext);
return null;
}
//AopNamespaceUtils
public static void registerAspectJAnnotationAutoProxyCreatorIfNecessary(
ParserContext parserContext, Element sourceElement) {
//生成AspectJAnnotationAutoProxyCreator 的beanDefinition信息并注册到容器中,
//name=org.springframework.aop.config.internalAutoProxyCreator
BeanDefinition beanDefinition = AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(
parserContext.getRegistry(), parserContext.extractSource(sourceElement));
//对 aspectj-autoproxy 的属性进行组装,比如proxy-target-class
useClassProxyingIfNecessary(parserContext.getRegistry(), sourceElement);
registerComponentIfNecessary(beanDefinition, parserContext);
}
接着在容器启动的过程中 registerBeanPostProcessors() 进行实例化。
提取advisors
获取加强proxy链路和配置方式一致,不同的在于注解方式获取advisors是代码自动提取的,AnnotationAwareAspectJAutoProxyCreator把AbstractAdvisorAutoProxyCreator的findCandidateAdvisors
覆盖了,有了自己的实现逻辑
//AnnotationAwareAspectJAutoProxyCreator
protected List<Advisor> findCandidateAdvisors() {
//调用父类的方法,检索容器中所有的advisor
List<Advisor> advisors = super.findCandidateAdvisors();
//构建加AspectJ注解的advisor
advisors.addAll(this.aspectJAdvisorsBuilder.buildAspectJAdvisors());
return advisors;
}
根据加@Aspect注解的bean生成advisors的调用链路
|--BeanFactoryAspectJAdvisorsBuilder.buildAspectJAdvisors
|----ReflectiveAspectJAdvisorFactory.getAdvisors
|------ReflectiveAspectJAdvisorFactory.getAdvisor
|--------new InstantiationModelAwarePointcutAdvisorImpl()
|----------InstantiationModelAwarePointcutAdvisorImpl.instantiateAdvice
|------------ReflectiveAspectJAdvisorFactory.getAdvice
//BeanFactoryAspectJAdvisorsBuilder
public List<Advisor> buildAspectJAdvisors() {
List<String> aspectNames = null;
//省略一大段代码,代码篇幅较长,可以认为 它把spring容器中的bean都拿了出来,
//然后判断是否添加了 @Aspect 注解
//根据提取出来的 @Aspect 进行进一步的组装,获取到具体的Advisor并添加到 advisors中返回
List<Advisor> advisors = new LinkedList<Advisor>();
for (String aspectName : aspectNames) {
//从缓存中读取已经生成的 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) 会找到所有加注解的方法
for (Method method : getAdvisorMethods(aspectClass)) {
Advisor advisor = getAdvisor(method, lazySingletonAspectInstanceFactory, advisors.size(), aspectName);
if (advisor != null) {
advisors.add(advisor);
}
}
// 省略部分代码,平时没有用到这些场景,这里就不解读了
return advisors;
}
getAdvisorMethods方法,会把所有带有注解的方法给提取出来,提取后会对方法进行排序,因为在后面设置advice order的时候有一个声明顺序,会起到一定的优先级影响。
//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);
}
}
});
//对方法进行排序
Collections.sort(methods, METHOD_COMPARATOR);
return methods;
}
方法的排序规则
Around.class, Before.class, After.class, AfterReturning.class, AfterThrowing.class
按照上面的注解顺序进行排序,如果不属于上面的注解类型,排序统一为方法总数量。
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(可以认为是当前加了@Aspect的advice类), pointcut 就是根据注解提取出来的
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);
//获取当前方法注解
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);
//设置advice的 声明顺序,当advice order 顺序一样的时候,该排序会有一定的影响
springAdvice.setDeclarationOrder(declarationOrderInAspect);
String[] argNames = this.parameterNameDiscoverer.getParameterNames(candidateAdviceMethod);
if (argNames != null) {
springAdvice.setArgumentNamesFromStringArray(argNames);
}
springAdvice.calculateArgumentBindings();
return springAdvice;
}
几个advice类型的类图我们看下
advice类图
Advisor 优先级
Advisor的优先级逻辑,配置方式和注解方式一致。
我们的advisor已经生成完毕,advisor的优先级排序逻辑入口在AspectJAwareAdvisorAutoProxyCreator.sortAdvisors。
Advisor排序链路
|--AspectJAwareAdvisorAutoProxyCreator.sortAdvisors
|----PartialOrder.sort
|------PartialOrder.addNewPartialComparable
|--------PartialOrder.addDirectedLinks
|----------AspectJPrecedenceComparator.compare
|------------AspectJPrecedenceComparator.comparePrecedenceWithinAspect
排序中最为关键的点
PartialOrder.addNewPartialComparable 这一步,将待排序的对象包装成PartialOrder.SortObject对象,这个对象有三个属性
//advisor holder
PartialComparable object;
//比当前advisor order 小的Advisors
List<SortObject> smallerObjects = new LinkedList<SortObject>();
//比当前advisor order 大的Advisors
List<SortObject> biggerObjects = new LinkedList<SortObject>();
PartialOrder.sort就是针对上面处理之后的SortObjects进行排序。
排序规则首先获取Advisor的order,小的优先级最高,如果order一样则取 declareOrder也就前面说的声明顺序,这里需要注意的是,声明顺序并发是和我们代码里的属性一致,它是经过排序的,排序逻辑向上可以找下。
当Advisor的order一样后,排序会进入到下面的逻辑
AspectJPrecedenceComparator.comparePrecedenceWithinAspect
private int comparePrecedenceWithinAspect(Advisor advisor1, Advisor advisor2) {
//两个Advisor 是否其中一个或者全部都是 after类型的Advisor
boolean oneOrOtherIsAfterAdvice =
(AspectJAopUtils.isAfterAdvice(advisor1) || AspectJAopUtils.isAfterAdvice(advisor2));
int adviceDeclarationOrderDelta = getAspectDeclarationOrder(advisor1) - getAspectDeclarationOrder(advisor2);
if (oneOrOtherIsAfterAdvice) {
//如果其中一个或者全部是 after类型的,先声明的优先级反而低
if (adviceDeclarationOrderDelta < 0) {
return LOWER_PRECEDENCE;
}
else if (adviceDeclarationOrderDelta == 0) {
return SAME_PRECEDENCE;
}
else {
return HIGHER_PRECEDENCE;
}
}
else {
//如果不是after类型的,哪个方法先声明则拥有更高的优先级。
if (adviceDeclarationOrderDelta < 0) {
return HIGHER_PRECEDENCE;
}
else if (adviceDeclarationOrderDelta == 0) {
return SAME_PRECEDENCE;
}
else {
return LOWER_PRECEDENCE;
}
}
}
4.4 proxy调用解读
本小节,三种aop使用方式的proxy创建和调用逻辑相同,所以放到一起进行讲解
创建proxy创建
//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创建proxy的api调用
return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this);
}
使用的是原生的jdk 动态代理api
proxy方法调用
当我们获得到proxy之后,然后调用业务方法的时候,执行链路最终到了 proxy的invoke方法。
调用链路
|--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 {
//省略部分代码
//获取当前执行对象匹配的advice chain
List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
if (chain.isEmpty()) {
//如果chain为空,直接执行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);
//开始执行逻辑,并返回结果
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);
}
}
}
获取当前方法的advice链,逻辑入口
AdvisedSupport.getInterceptorsAndDynamicInterceptionAdvice
具体实现在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();
//循环当前targetClass的advisors
for (Advisor advisor : config.getAdvisors()) {
if (advisor instanceof PointcutAdvisor) {
//获取当前advisor的pointcut
PointcutAdvisor pointcutAdvisor = (PointcutAdvisor) advisor;
if (config.isPreFiltered() || pointcutAdvisor.getPointcut().getClassFilter().matches(targetClass)) {
//根据advisor获取interceptors
MethodInterceptor[] interceptors = registry.getInterceptors(advisor);
MethodMatcher mm = pointcutAdvisor.getPointcut().getMethodMatcher();
//判断当前方法是否匹配当前advisor的pointcut
if (MethodMatchers.matches(mm, method, targetClass, hasIntroductions)) {
if (mm.isRuntime()) {
for (MethodInterceptor interceptor : interceptors) {
interceptorList.add(new InterceptorAndDynamicMethodMatcher(interceptor, mm));
}
}
else {
//将当前advisor对应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;
}
如何根据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实例化的时候完成装配
public DefaultAdvisorAdapterRegistry() {
registerAdvisorAdapter(new MethodBeforeAdviceAdapter());
registerAdvisorAdapter(new AfterReturningAdviceAdapter());
registerAdvisorAdapter(new ThrowsAdviceAdapter());
}
这些adapters判断是否支持当前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);
}
现在我们获取到了当前方法匹配的MethodInterceptor,最后也就是 MethodInterceptor chain。接下来看下具体的执行逻辑ReflectiveMethodInvocation.proceed()
public Object proceed() throws Throwable {
//interceptors chain执行完毕,则开始执行target的method
if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {
return invokeJoinpoint();
}
//MethodInterceptor chain每执行一个,currentInterceptorIndex + 1
Object interceptorOrInterceptionAdvice =
this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex);
if (interceptorOrInterceptionAdvice instanceof InterceptorAndDynamicMethodMatcher) {
//省略代码,本篇使用的样例,不会走到该逻辑
}
else {
// 按照 MethodInterceptor chain执行逻辑
return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this);
}
}
jdk的动态代理就介绍到这了,cglib方式的先不介绍了,当然本篇也并非面面俱到,如果有朋友对本篇没有提及部分感兴趣的话,可以按照这个思路自己探索一番。
有兴趣的朋友可以自行研究下,这里就不介绍了。
五、Spring AOP 不生效的探索
在使用spring aop的时候,可能我们会时不时的出现aop不生效的问题,最常见的莫过于spring的事务,为什么有时候不生效呢?
代理类结构内视图
通过上面的几个章节,这个图大家不难理解,
前提
我们有 method A 和 methodB的两个切面
case1:调用 C.A, 方法A切面生效
case2: 调用C.B, 方法B切面生效
case3: 调用C.A, C.A调用C.B,方法A切面生效, 方法B切面失效。
通过图中表述,当方法A切面生效的时候,调用到 目标类C的B方法,这时候调用B的对象是目标类C而非 代理对象,所以对方法B的加强会不起作用
文章开头的问题答案如下:
输出内容
快点睡觉!!!
睡觉前要脱衣服!
睡觉!不休息哪里有力气学习!
lalala
睡着了!!!
睡醒了要穿衣服!
系列文章
spring源码探索(0)-IOC容器-架构设计
spring源码探索(1)-IOC容器-Resource
spring源码探索(2)-IOC容器-BeanDefinition加载与注册
spring源码探索(3)-IOC容器-Bean的一生
spring源码探索(4)-AOP实现原理
网友评论