Spring AOP 简单分析

指在程序运行期间动态的将某段代码切入到指定方法指定位置进行运行的编程方式

步骤

  1. 导入aop模块:Spring AOP(Spring-aspects)

  2. 定义业务逻辑类(MathCalculator):在业务逻辑运行的时候将日志进行打印(方法之前、方法运行结束、方法正常返回等等)

  3. 定义日志切面类(LogAspects):切面类里面的方法需要动态感知MathCalculator.div运行到哪儿了。通知方法:

    • 前置通知(@Before):logStart(在目标方法(div)运行之前运行)

    • 后置通知(@After):logEnd(在目标方法(div)运行结束之后运行)

    • 返回通知(@AfterReturning):logReturning(在目标方法(div)正常返回之后运行)

    • 异常通知(@AfterThrowing):logThrow(在目标方法(div)出现异常以后运行)

    • 环绕通知(@Around):logAround (动态代理,手动推进目标方法运行ProceedingJoinPoint.proceed)

  4. 给切面类的目标方法标注何时运行(通知注解@Before等)

  5. 必须告诉Spring哪个类是切面类(给切面类上加注解:@Aspect)

  6. 将切面类和业务逻辑类(目标方法所在类)加入容器

  7. 给配置类中加 @EnableAspectJAutoProxy【开启基于注解的aop模式】。在Spring中有很多@Enablexxx(开始xxx的注解模式)

业务类


public class MathCalculator {

    public int dev(int i, int j) {

        System.out.println("MathCalculator。。。div");

        return i/j;

    }

}

日志切面类


import org.aspectj.lang.JoinPoint;

import org.aspectj.lang.ProceedingJoinPoint;

import org.aspectj.lang.annotation.*;

import java.util.Arrays;

@Aspect // 告诉Spring这是一个切面类

public class LogAspects {

    // 抽取公共的切入点表达式

    @Pointcut("execution(public int test.aop.MathCalculator.*(..))")

    public void pointCut() {

    }

    @Before("pointCut()")// 本类引用

    public void logStart(JoinPoint joinPoint) {

        System.out.println(joinPoint.getSignature().getName() + "运行。。。参数列表是:{" + Arrays.toString(joinPoint.getArgs()) + "}");

    }

    @After("test.aop.LogAspects.pointCut()")// 其他的切面引用

    public void logEnd(JoinPoint joinPoint) {

        System.out.println(joinPoint.getSignature().getName() + "结束。。。");

    }

    @AfterReturning(value = "pointCut()", returning = "result")

    public void logReturn(JoinPoint joinPoint, int result) {

        System.out.println(joinPoint.getSignature().getName() + "正常返回。。。返回值" + result);

    }



    @AfterThrowing(value = "pointCut()", throwing = "exception")

    public void logThrow(JoinPoint joinPoint, Exception exception) {

        System.out.println(joinPoint.getSignature().getName() + "异常。。。异常信息" + exception);

    }

    // JoinPoint 一定要出现在参数表的第一位,不然会报错

    @Around("pointCut()")

    public Object logAround(ProceedingJoinPoint pjp) throws Throwable {

        System.out.println(pjp.getSignature().getName() + "before around。。。参数值" + Arrays.toString(pjp.getArgs()));

        Object proceed = pjp.proceed();

        System.out.println(pjp.getSignature().getName() + "after around。。。返回值" + proceed);

        return proceed;

    }

}

配置类


import org.springframework.context.annotation.Bean;

import org.springframework.context.annotation.ComponentScan;

import org.springframework.context.annotation.Configuration;

import org.springframework.context.annotation.EnableAspectJAutoProxy;

import test.aop.LogAspects;

import test.aop.MathCalculator;

@Configuration

@ComponentScan("test.aop")

@EnableAspectJAutoProxy

public class ConfigOfAop {

    @Bean

    public MathCalculator mathCalculator() {

        return new MathCalculator();

    }

    @Bean

    public LogAspects logAspects() {

        return new LogAspects();

    }

}

启动类


AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(ConfigOfAop.class);

MathCalculator mathCalculator =  context.getBean(MathCalculator.class);

mathCalculator.dev(1,1);

1/1 打印结果


devbefore around。。。参数值[1, 1]

dev运行。。。参数列表是:{[1, 1]}

MathCalculator。。。div

devafter around。。。返回值1

dev结束。。。

dev正常返回。。。返回值1

1/0 打印结果


devbefore around。。。参数值[1, 0]

dev运行。。。参数列表是:{[1, 0]}

MathCalculator。。。div

dev结束。。。

dev异常。。。异常信息java.lang.ArithmeticException: / by zero

Exception in thread "main" java.lang.ArithmeticException: / by zero

at test.aop.MathCalculator.dev(MathCalculator.java:8)

...

原理分析

  1. 先从 @EnableAspectJAutoProxy 注解分析

@Target(ElementType.TYPE)

@Retention(RetentionPolicy.RUNTIME)

@Documented

@Import(AspectJAutoProxyRegistrar.class)

public @interface EnableAspectJAutoProxy {

...

AspectJAutoProxyRegistrar继承了ImportBeanDefinitionRegistrar接口。手动注册bean到容器中。


class AspectJAutoProxyRegistrar implements ImportBeanDefinitionRegistrar {

...

public void registerBeanDefinitions(

AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {

        // 注入bean到容器中

AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry);

...

一直点击方法registerAspectJAnnotationAutoProxyCreatorIfNecessary->registerAspectJAnnotationAutoProxyCreatorIfNecessary->registerOrEscalateApcAsRequired


public static BeanDefinition registerAspectJAnnotationAutoProxyCreatorIfNecessary(

BeanDefinitionRegistry registry, @Nullable Object source) {

return registerOrEscalateApcAsRequired(AnnotationAwareAspectJAutoProxyCreator.class, registry, source);

}

registerOrEscalateApcAsRequired方法把AnnotationAwareAspectJAutoProxyCreator注册到容器中,名字:org.springframework.aop.config.internalAutoProxyCreator


private static BeanDefinition registerOrEscalateApcAsRequired(

Class<?> cls, BeanDefinitionRegistry registry, @Nullable Object source) {

...

RootBeanDefinition beanDefinition = new RootBeanDefinition(cls);

beanDefinition.setSource(source);

beanDefinition.getPropertyValues().add("order", Ordered.HIGHEST_PRECEDENCE);

beanDefinition.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);

registry.registerBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME, beanDefinition);

return beanDefinition;

}

  1. 再看看 AnnotationAwareAspectJAutoProxyCreator是干啥的

继承关系

AnnotationAwareAspectJAutoProxyCreator

->AspectJAwareAdvisorAutoProxyCreator

->AbstractAdvisorAutoProxyCreator

->AbstractAutoProxyCreator extends ProxyProcessorSupport

implements SmartInstantiationAwareBeanPostProcessor,BeanFactoryAware

ProxyProcessorSupport extends ProxyConfig implements Ordered

SmartInstantiationAwareBeanPostProcessor extends InstantiationAwareBeanPostProcessor

发现这个类是一个后置处理器(在bean初始化完成前后调用),会自动装配 BeanFactory,并实现了 Ordered

AbstractAutoProxyCreator 有BeanFactory装配、后置处理器逻辑


@Override

public void setBeanFactory(BeanFactory beanFactory) {

this.beanFactory = beanFactory;

}

...

@Override

public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) {

...

@Override

public boolean postProcessAfterInstantiation(Object bean, String beanName) {

return true;

}

AbstractAdvisorAutoProxyCreator.setBeanFactory -> initBeanFactory


@Override

public void setBeanFactory(BeanFactory beanFactory) {

super.setBeanFactory(beanFactory);

if (!(beanFactory instanceof ConfigurableListableBeanFactory)) {

throw new IllegalArgumentException(

"AdvisorAutoProxyCreator requires a ConfigurableListableBeanFactory: " + beanFactory);

}

initBeanFactory((ConfigurableListableBeanFactory) beanFactory);

}

AnnotationAwareAspectJAutoProxyCreator.initBeanFactory 对

BeanFactory 进行一层包装成

ReflectiveAspectJAdvisorFactory


@Override

protected void initBeanFactory(ConfigurableListableBeanFactory beanFactory) {

super.initBeanFactory(beanFactory);

if (this.aspectJAdvisorFactory == null) {

this.aspectJAdvisorFactory = new ReflectiveAspectJAdvisorFactory(beanFactory);

}

this.aspectJAdvisorsBuilder =

new BeanFactoryAspectJAdvisorsBuilderAdapter(beanFactory, this.aspectJAdvisorFactory);

}

流程

  1. 传入配置类,创建ioc容器

AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(ConfigOfAop.class);

  1. 注册配置类,调用 refresh() 刷新容器

public AnnotationConfigApplicationContext(Class<?>... componentClasses) {

this();

register(componentClasses);

refresh();

}

  1. 注册 bean 的后置处理器来方便拦截 bean 的创建

public void refresh() throws BeansException, IllegalStateException {

    ...

    // Register bean processors that intercept bean creation.

    registerBeanPostProcessors(beanFactory);

    ....


public static void registerBeanPostProcessors(

ConfigurableListableBeanFactory beanFactory, AbstractApplicationContext applicationContext) {

    // 1. 先获取ioc容器已经定义了的需要创建对象的所有BeanPostProcessor

String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanPostProcessor.class, true, false);

    ...

    // 2. 区分 实现了 PriorityOrdered、Ordered、没实现优先级 的BeanPostProcessor

    // 3. 优先实现了 PriorityOrdered 接口的 BeanPostProcessor

sortPostProcessors(priorityOrderedPostProcessors, beanFactory);

registerBeanPostProcessors(beanFactory, priorityOrderedPostProcessors);

    // 4. 再给容器注册实现了 Ordered 的 BeanPostProcessor

List<BeanPostProcessor> orderedPostProcessors = new ArrayList<>(orderedPostProcessorNames.size());

for (String ppName : orderedPostProcessorNames) {

    // 获取对象,没有创建

BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);

orderedPostProcessors.add(pp);

if (pp instanceof MergedBeanDefinitionPostProcessor) {

internalPostProcessors.add(pp);

}

}

sortPostProcessors(orderedPostProcessors, beanFactory);

registerBeanPostProcessors(beanFactory, orderedPostProcessors);



    // 5. 注册没实现优先级接口的 BeanPostProcessor

registerBeanPostProcessors(beanFactory, nonOrderedPostProcessors);

// 6. 最后,重新注册所有内部 BeanPostProcessor。

sortPostProcessors(internalPostProcessors, beanFactory);

registerBeanPostProcessors(beanFactory, internalPostProcessors);

// 重新注册后处理器以将内部bean检测为ApplicationListener,将其移至处理器链的末尾(用于拾取代理等)

beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(applicationContext));

}


private static void registerBeanPostProcessors(

ConfigurableListableBeanFactory beanFactory, List<BeanPostProcessor> postProcessors) {

for (BeanPostProcessor postProcessor : postProcessors) {

beanFactory.addBeanPostProcessor(postProcessor);

}

}

由于 AnnotationAwareAspectJAutoProxyCreator 是实现了 Ordered 的接口,会在第4步注册到容器中

  1. BeanPostProcessor 注册流程

注册 BeanPostProcessor,实际上就是创建 BeanPostProcessor 对象,保存在容器中。创建 org.springframework.aop.config.internalAutoProxyCreator 的 BeanPostProcessor【AnnotationAwareAspectJAutoProxyCreator】

beanFactory.getBean() -> doGetBean() -> createBean() -> doCreateBean()

先从缓存中获取当前bean,如果能获取到,说明bean是之前被创建过的,直接使用,否则再创建;只要创建好的bean都会缓存起来


protected <T> T doGetBean(final String name, @Nullable final Class<T> requiredType,

@Nullable final Object[] args, boolean typeCheckOnly) throws BeansException {

...

// 认真检查单例缓存是否有手动注册的单例

Object sharedInstance = getSingleton(beanName);

...

// 创建 bean

return createBean(beanName, mbd, args);

...


@Override

protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)

throws BeanCreationException {

...

// 给BeanPostProcessors一个返回代理而不是目标bean实例的机会

Object bean = resolveBeforeInstantiation(beanName, mbdToUse);

...

Object beanInstance = doCreateBean(beanName, mbdToUse, args);

...

}

doCreateBean()


protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args)

throws BeanCreationException {

...

// 1. 创建 bean 的实例

instanceWrapper = createBeanInstance(beanName, mbd, args);

...

// 2. 给 bean 的各种熟性赋值

populateBean(beanName, mbd, instanceWrapper);

// 3. 初始化bean

exposedObject = initializeBean(beanName, exposedObject, mbd);

...

// Register bean as disposable.

try {

registerDisposableBeanIfNecessary(beanName, bean, mbd);

}

...

}

initializeBean()


protected Object initializeBean(final String beanName, final Object bean, @Nullable RootBeanDefinition mbd) {

    ...

    // 1. 处理 Aware接口的方法回调 比如 BeanFactoryAware(装配BeanFactory)

    invokeAwareMethods(beanName, bean);

    ...

    // 2. 执行后置处理器的postProcessBeforeInitialization() 方法

    wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);

    ...

    // 3. 执行自定义的初始化方法

    invokeInitMethods(beanName, wrappedBean, mbd);

    ...

    // 4. 执行后置处理器的 postProcessBeforeInitialization() 方法

    wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);

}

至此 AnnotationAwareAspectJAutoProxyCreator 创建完成;AnnotationAwareAspectJAutoProxyCreator【BeanPostProcessor】会注册到 BeanFactory中 beanFactory.addBeanPostProcessor(postProcessor);

  1. 业务类的创建流程和切面类的创建流程

public void refresh() throws BeansException, IllegalStateException {

    ...

    // Register bean processors that intercept bean creation.

    registerBeanPostProcessors(beanFactory);

    ...

    // 实例化所有剩余的(非延迟初始化)单例。

    finishBeanFactoryInitialization(beanFactory);

    ...

}

finishBeanFactoryInitialization() -> beanFactory.preInstantiateSingletons()

遍历获取容器中所有的Bean,依次创建对象 getBean(beanName)


@Override

public void preInstantiateSingletons() throws BeansException {

    ...

    List<String> beanNames = new ArrayList<>(this.beanDefinitionNames);

    ...

    for (String beanName : beanNames) {

        ...

        getBean(beanName);

        ...

}

}

beanFactory.getBean() -> doGetBean() -> createBean()


// 给BeanPostProcessors一个返回代理而不是目标bean实例的机会

Object bean = resolveBeforeInstantiation(beanName, mbdToUse);

resolveBeforeInstantiation 希望后置处理器在此返回一个代理对象,如果能返回代理对象就使用,如果不能就继续


protected Object resolveBeforeInstantiation(String beanName, RootBeanDefinition mbd) {

...

bean = applyBeanPostProcessorsBeforeInstantiation(targetType, beanName);

if (bean != null) {

bean = applyBeanPostProcessorsAfterInitialization(bean, beanName);

}

...

}

拿到所有的后置处理器,如果是 InstantiationAwareBeanPostProcessor 就执行 postProcessBeforeInstantiation;而 AnnotationAwareAspectJAutoProxyCreator 实现了 InstantiationAwareBeanPostProcessor,在所有bean创建之前会有一个拦截,在任何 bean 创建之前尝试返回 bean 的实例


protected Object applyBeanPostProcessorsBeforeInstantiation(Class<?> beanClass, String beanName) {

for (BeanPostProcessor bp : getBeanPostProcessors()) {

if (bp instanceof InstantiationAwareBeanPostProcessor) {

InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;

Object result = ibp.postProcessBeforeInstantiation(beanClass, beanName);

if (result != null) {

return result;

}

}

}

return null;

}

doCreateBean() 真正去创建一个 bean 实例;和上面 BeanPostProcessor 注册的创建流程一样

  1. AnnotationAwareAspectJAutoProxyCreator 的作用

postProcessBeforeInstantiation


@Override

public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) {

Object cacheKey = getCacheKey(beanClass, beanName);

if (!StringUtils.hasLength(beanName) || !this.targetSourcedBeans.contains(beanName)) {

    // 1. 判断当前bean是否在advisedBeans中(保存了所有需要增强bean)

if (this.advisedBeans.containsKey(cacheKey)) {

return null;

}

// 2. 判断是否是基础类型的 Advice、Pointcut、Advisor、AopInfrastructureBean或者是否是切面(@Aspect)

// 3. 是否需要跳过

if (isInfrastructureClass(beanClass) || shouldSkip(beanClass, beanName)) {

this.advisedBeans.put(cacheKey, Boolean.FALSE);

return null;

}

}



    // 是否有自定义的 TargetSource

TargetSource targetSource = getCustomTargetSource(beanClass, beanName);

if (targetSource != null) {

if (StringUtils.hasLength(beanName)) {

this.targetSourcedBeans.add(beanName);

}

Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(beanClass, beanName, targetSource);

Object proxy = createProxy(beanClass, beanName, specificInterceptors, targetSource);

this.proxyTypes.put(cacheKey, proxy.getClass());

return proxy;

}

return null;

}

shouldSkip 是否需要跳过


@Override

protected boolean shouldSkip(Class<?> beanClass, String beanName) {

// 获取候选的增强器(切面里面的通知方法)

List<Advisor> candidateAdvisors = findCandidateAdvisors();

for (Advisor advisor : candidateAdvisors) {

    // AspectJPointcutAdvisor 是否是这个类型

if (advisor instanceof AspectJPointcutAdvisor &&

((AspectJPointcutAdvisor) advisor).getAspectName().equals(beanName)) {

return true;

}

}

return super.shouldSkip(beanClass, beanName);

}

创建完对象执行 postProcessAfterInitialization


@Override

public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) {

if (bean != null) {

Object cacheKey = getCacheKey(bean.getClass(), beanName);

if (this.earlyProxyReferences.remove(cacheKey) != bean) {

    // 如果需要包装

return wrapIfNecessary(bean, beanName, cacheKey);

}

}

return bean;

}

wrapIfNecessary


protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {

    ...

// 进行 postProcessBeforeInstantiation 一样的判断

    ...

// 获取当前bean的所有增强器(通知方法)

Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);

if (specificInterceptors != DO_NOT_PROXY) {

    // 保存在advisedBeans

this.advisedBeans.put(cacheKey, Boolean.TRUE);

// 如果当前bean需要增强,创建当前bean的代理对象

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;

}

getAdvicesAndAdvisorsForBean()->findEligibleAdvisors()


protected List<Advisor> findEligibleAdvisors(Class<?> beanClass, String beanName) {

    // 找到候选的增强器

List<Advisor> candidateAdvisors = findCandidateAdvisors();

// findAdvisorsThatCanApply->AopUtils.findAdvisorsThatCanApply()-> canApply()(解析切面表达式能不能匹配)

// 找到能在 bean 使用的增强器

List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);

extendAdvisors(eligibleAdvisors);

if (!eligibleAdvisors.isEmpty()) {

    // 给增强器进行排序

eligibleAdvisors = sortAdvisors(eligibleAdvisors);

}

return eligibleAdvisors;

}

createProxy() -> proxyFactory.getProxy(getProxyClassLoader()) -> createAopProxy().getProxy(classLoader) -> getAopProxyFactory().createAopProxy(this)

创建代理对象:Spring 自动决定

JdkDynamicAopProxy: jdk 动态代理

ObjenesisCglibAopProxy:cglib 动态代理

以后容器中获取的就是这个组件的代理对象,执行目标方法的时候,代理对象会执行通知方法的流程


@Override

public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {

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() || Proxy.isProxyClass(targetClass)) {

return new JdkDynamicAopProxy(config);

}

return new ObjenesisCglibAopProxy(config);

    }

    else {

    return new JdkDynamicAopProxy(config);

    }

}

所以在默认情况下,如果一个目标对象如果实现了接口Spring则会选择JDK动态代理策略动态的创建一个接口实现类(动态代理类)来代理目标对象,可以通俗的理解这个动态代理类是目标对象的另外一个版本,所以这两者之间在强制转换的时候会抛出java.lang.ClassCastException。而所以在默认情况下,如果目标对象没有实现任何接口,Spring会选择CGLIB代理, 其生成的动态代理对象是目标类的子类。

上说的是默认情况下,也可以手动配置一些选项使Spring采用CGLIB代理。

org.springframework.transaction.interceptor.TransactionProxyFactoryBean是org.springframework.aop.framework. ProxyConfig的子类,所以可以参照ProxyConfig里的一些设置如下所示,将optimize和proxyTargetClass任意一个设置为true都可以强制Spring采用CGLIB代理。

如果当需要使用CGLIB代理和@AspectJ自动代理支持,请按照如下的方式设置 |aop:aspectj-autoproxy| 的 proxy-target-class 属性:


|aop:aspectj-autoproxy proxy-target-class="true"/|

如果是 JDK 代理,名字是类似$Proxy75


// Ss 是接口,用以下两种方式任意一种从容器中获取

Ss mathCalculator = (Ss) context.getBean("mathCalculator");

mathCalculator = context.getBean(Ss.class);

  1. 目标方法执行

容器保存了组件的代理对象(cglib/jdk增强后的对象),这个对象里面保存了详细信息(比如增强器,目标对象等待)

  1. CglibAopProxy.intercept() / JdkDynamicAopProxy.invoke() 拦截了目标方法的执行

@Override

@Nullable

public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {

    ...

    // 获取将要执行的目标方法拦截器链

List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);

Object retVal;

...

// 没有拦截器,直接执行目标方法

if (chain.isEmpty() && Modifier.isPublic(method.getModifiers())) {

Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);

retVal = methodProxy.invoke(target, argsToUse);

}

else {

    // 如果有拦截器,把需要执行的目标对象,目标方法,拦截器链等信息传入创建一个 CglibMethodInvocation,然后执行

retVal = new CglibMethodInvocation(proxy, target, method, args, targetClass, chain, methodProxy).proceed();

}

retVal = processReturnType(proxy, target, method, retVal);

return retVal;

    ...

}

getInterceptorsAndDynamicInterceptionAdvice() -> advisorChainFactory.getInterceptorsAndDynamicInterceptionAdvice()

便利所有的增强器,将其转为 MethodInterceptor:registry.getInterceptors(advisor);


@Override

public MethodInterceptor[] getInterceptors(Advisor advisor) throws UnknownAdviceTypeException {

List<MethodInterceptor> interceptors = new ArrayList<>(3);

// 如果是MethodInterceptor,直接加入

Advice advice = advisor.getAdvice();

if (advice instanceof MethodInterceptor) {

interceptors.add((MethodInterceptor) advice);

}

for (AdvisorAdapter adapter : this.adapters) {

    // 如果不是,利用 AdvisorAdapter将增强器转为 MethodInterceptor

if (adapter.supportsAdvice(advice)) {

interceptors.add(adapter.getInterceptor(advisor));

}

}

if (interceptors.isEmpty()) {

throw new UnknownAdviceTypeException(advisor.getAdvice());

}

return interceptors.toArray(new MethodInterceptor[0]);

}

增强器链的调用

CglibMethodInvocation.proceed();

链式获取每一个拦截器,拦截执行invoke方法,每一个拦截器等待下一个拦截器执行完成返回以后再执行。拦截器链的机制,保证通知方法与目标方法的执行顺序。


Override

@Nullable

public Object proceed() throws Throwable {

    // 如果没有拦截器链执行目标方法,或者拦截器的索引和拦截器数组-1大小一样(执行到了最后一个拦截器)执行目标方法

// We start with an index of -1 and increment early.

if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {

return invokeJoinpoint();

}

Object interceptorOrInterceptionAdvice =

this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex);

if (interceptorOrInterceptionAdvice instanceof InterceptorAndDynamicMethodMatcher) {

// Evaluate dynamic method matcher here: static part will already have

// been evaluated and found to match.

InterceptorAndDynamicMethodMatcher dm =

(InterceptorAndDynamicMethodMatcher) interceptorOrInterceptionAdvice;

Class<?> targetClass = (this.targetClass != null ? this.targetClass : this.method.getDeclaringClass());

if (dm.methodMatcher.matches(this.method, targetClass, this.arguments)) {

return dm.interceptor.invoke(this);

}

else {

// Dynamic matching failed.

// Skip this interceptor and invoke the next in the chain.

return proceed();

}

}

else {

// It's an interceptor, so we just invoke it: The pointcut will have

// been evaluated statically before this object was constructed.

return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this);

}

}

增强器链的流程图

流程.png
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
禁止转载,如需转载请通过简信或评论联系作者。
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 222,681评论 6 517
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 95,205评论 3 399
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 169,421评论 0 362
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 60,114评论 1 300
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 69,116评论 6 398
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 52,713评论 1 312
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 41,170评论 3 422
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 40,116评论 0 277
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 46,651评论 1 320
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 38,714评论 3 342
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,865评论 1 353
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 36,527评论 5 351
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 42,211评论 3 336
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 32,699评论 0 25
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,814评论 1 274
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 49,299评论 3 379
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 45,870评论 2 361