Spring5.0源码深度解析之SpringBean的Aop通知调用链源码分析

思考:springAOP底层运用了什么设计模式?

生成代理类:代理设计模式、底层五个通知形成调用链采用:责任链设计模式

下面我们回顾下SpringAop实现流程:

1、配置@EnableAspectJAutoProxy 2、@Import(AspectJAutoProxyRegistrar.class)往IOC容器中注入SpringAOP切面类 3、registerAspectJAnnotationAutoProxyCreatorIfNecessary()注册切面类 4、AnnotationAwareAspectJAutoProxyCreator.class注册到IOC容器中,【AOP的入口】 5、postProcessAfterInitialization 6、wrapIfNecessary()判断该对象是否在AOP的扫包范围内 7、createAopProxy()判断被代理类是否实现了接口,如果有实现了接口的化,是采用JDK动态代理,否则情况下就使用CGLIB代理 8、使用JdkDynamicAopProxy()方法实现代理类 9、最终执行目标方法的时候,就会进入到JdkDynamicAopProxy 的invoke()方法 10、底层使用集合存放使用通知,然后再使用责任链设计模式循环的调用

如果调用了目标方法,则最终进入invoke方法

SpringBean的生命周期

主要靠的是后置处理器BeanPostProcessor:在Bean对象初始化前后做一些增强 AnnotationAwareAspectJAutoProxyCreator的祖宗是BeanPostProcessor

纯手写SpringAop调用链思路

【0】环绕通知之前执行→【1】前置通知→目标方法→【2】后置通知→【3】环绕通知之后执行 责任链设计模式,底层通过递归算法+责任链 如何存放起来:使用集合存放这些通知,集合当中不存放我们的方法,只存放链,那么如何插入我们的目标方法?

纯手写SpringAop调用链

MethodInterceptor 接口

public interface MethodInterceptor {
    /**
     * 定义共同通知骨架
     */
    public void invoke(MethodInvocation methodInvocation) throws InvocationTargetException, IllegalAccessException;
}

BeforMethodInterceptor 前置通知

public class BeforMethodInterceptor implements MethodInterceptor {
    public void invoke(MethodInvocation methodInvocation) throws InvocationTargetException, IllegalAccessException {
        System.out.println(">>>>前置通知<<<<");
        // 执行我们的目标方法
        methodInvocation.process();// 递归调用
    }
}

AfterMethodInterceptor后置通知

public class AfterMethodInterceptor implements MethodInterceptor {
    public void invoke(MethodInvocation methodInvocation) throws InvocationTargetException, IllegalAccessException {
        // 执行我们的前置通知
        methodInvocation.process();
        System.out.println(">>>后置通知<<<");
    }
}

AroundMethodInterceptor 环绕通知

public class AroundMethodInterceptor implements MethodInterceptor {
    public void invoke(MethodInvocation methodInvocation) throws InvocationTargetException, IllegalAccessException {
        System.out.println("环绕通知在目标方法之前执行..");
        methodInvocation.process();
        System.out.println("环绕通知在目标方法之后执行..");
    }
}

UserService

public class UserService {
    public void login(String userName, Integer age) {
        System.out.println("userName:" + userName + ",age:" + age);
    }
}

MethodInvocation 能够把链串起来

public interface MethodInvocation {
    //调用链形成
    public void process() throws InvocationTargetException, IllegalAccessException;

}

DefaultMethodInvacation 实现通知串起来

public class DefaultMethodInvacation implements MethodInvocation {
    /**
     * 存放所有的通知
     */
    private List<MethodInterceptor> listMethodInterceptor;
    private Object target;// 目标对象
    private Method method;// 目标方法
    private Object args[];// 目标参数
    // 最终使用反射机制执行目标方法
    private int index;// 记录当前链调用的位置
    public DefaultMethodInvacation(List<MethodInterceptor> listMethodInterceptor, Object target, Method method, Object[] args) {
        this.listMethodInterceptor = listMethodInterceptor;
        this.target = target;
        this.method = method;
        this.args = args;
    }
    /**
     * 调用链形成
     */
    @Override
    public void process() throws InvocationTargetException, IllegalAccessException {
        if (index == listMethodInterceptor.size()) {
            method.invoke(target, args); //  执行目标
            return;
        }
        MethodInterceptor methodInterceptor = listMethodInterceptor.get(index++);
        methodInterceptor.invoke(this);
    }
}

执行结果:

>>>>前置通知<<<< 环绕通知在目标方法之前执行.. userName:mayikt,age:12 环绕通知在目标方法之后执行.. >>>后置通知<<<

下面我们看下源码是如何实现的

源码分析SpringAop

入口:

AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MyConfig.class);
// Instantiate all remaining (non-lazy-init) singletons.
finishBeanFactoryInitialization(beanFactory);
// Instantiate all remaining (non-lazy-init) singletons.
beanFactory.preInstantiateSingletons();
if (isEagerInit) {
    this.getBean(beanName);
}
public Object getBean(String name) throws BeansException {
    return this.doGetBean(name, (Class)null, (Object[])null, false);
}
if (mbd == null || !mbd.isSynthetic()) {
    wrappedBean = this.applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
}
return proxyFactory.getProxy(this.getProxyClassLoader());
public Object getProxy(@Nullable ClassLoader classLoader) {
    return this.createAopProxy().getProxy(classLoader);
}

执行目标方面会进入invoke()方法

public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
   ...
    try {
      ....
            } else {
                MethodInvocation invocation = new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain);
                retVal = invocation.proceed();
            }
      ....
}
public Object proceed() throws Throwable {
    if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {
        return this.invokeJoinpoint();
    } else {
        Object interceptorOrInterceptionAdvice = this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex);
        if (interceptorOrInterceptionAdvice instanceof InterceptorAndDynamicMethodMatcher) {
            InterceptorAndDynamicMethodMatcher dm = (InterceptorAndDynamicMethodMatcher)interceptorOrInterceptionAdvice;
            return dm.methodMatcher.matches(this.method, this.targetClass, this.arguments) ? dm.interceptor.invoke(this) : this.proceed();
        } else {
            return ((MethodInterceptor)interceptorOrInterceptionAdvice).invoke(this);
        }
    }
}

这里就是那五个通知后面还有个TransactionInterceptor,后面会分析它

本文参考

蚂蚁课堂:http://www.mayikt.com/

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

扫码关注云+社区

领取腾讯云代金券