• spring aop 初探


    org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator#wrapIfNecessary

    分析JDK动态代理

    生成的代理对象  构造函数,入参为 InvocationHandler

    public com.sun.proxy.$Proxy164(java.lang.reflect.InvocationHandler)

    生成动态代理Class对象:

    Class cl = getProxyClass0(loader, intfs);

    实例化动态代理对象:

    final Constructor cons = cl.getConstructor({ InvocationHandler.class });

    cons.newInstance(new Object[]{h});

    方法

    equals,toString,hashCode 

    0 = {Method@10598} "public final boolean com.sun.proxy.$Proxy164.equals(java.lang.Object)"
    1 = {Method@10599} "public final java.lang.String com.sun.proxy.$Proxy164.toString()"
    2 = {Method@10600} "public final int com.sun.proxy.$Proxy164.hashCode()"

    和 所有代理接口中的 所有方法。

    代理对象的方法实现逻辑:比如 equals方法

    return ((Boolean)this.h.invoke(this, m1, new Object[] { paramObject })).booleanValue();

    就是调用 

    java.lang.reflect.InvocationHandler#invoke

    1. public interface InvocationHandler {
    2. public Object invoke(Object proxy, Method method, Object[] args) throws Throwable;
    3. }

     第一个参数,代理对象本身

    第二个参数,调用的代理的接口中的方法

    第三个参数,调用的方法 入参

    JDK动态代理 需要开发者关注的,就是 实现 InvocationHandler 接口。实际 也并不需要很复杂的实现,可以引用另一个服务来实现。

    org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator

    在spring 实例化 bean之后,会执行

    1. public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) {
    2. if (bean != null) {
    3. Object cacheKey = getCacheKey(bean.getClass(), beanName);
    4. if (this.earlyProxyReferences.remove(cacheKey) != bean) {
    5. return wrapIfNecessary(bean, beanName, cacheKey);
    6. }
    7. }
    8. return bean;
    9. }

    完成aop 代理对象的生成。

    JDK动态代理的 InvocationHandler 的实现类为 JdkDynamicAopProxy,其增强功能由 advised 完成。和上面画的结构 基本一致。

    Advisor

    寻找Advisor

    1. // org.springframework.aop.aspectj.annotation.AnnotationAwareAspectJAutoProxyCreator#findCandidateAdvisors
    2. protected List findCandidateAdvisors() {
    3. // Add all the Spring advisors found according to superclass rules.
    4. List advisors = super.findCandidateAdvisors();
    5. // Build Advisors for all AspectJ aspects in the bean factory.
    6. if (this.aspectJAdvisorsBuilder != null) {
    7. advisors.addAll(this.aspectJAdvisorsBuilder.buildAspectJAdvisors());
    8. }
    9. return advisors;
    10. }

    第一部分,直接查找所有的 Advisor类型的bean

    this.beanFactory.getBean(name, Advisor.class)

    第二部分,查询标有 @Aspect 注解的 bean

    1. private boolean hasAspectAnnotation(Class clazz) {
    2. return (AnnotationUtils.findAnnotation(clazz, Aspect.class) != null);
    3. }

     针对每个bean,找到所有 没有标记 @Pointcut 注解的方法

    对每个方法查找对应的切面,标记 标记 @Around等注解的方法

    1. private static final Class[] ASPECTJ_ANNOTATION_CLASSES = new Class[] {
    2. Pointcut.class, Around.class, Before.class, After.class, AfterReturning.class, AfterThrowing.class};
    3. protected enum AspectJAnnotationType {
    4. AtPointcut, AtAround, AtBefore, AtAfter, AtAfterReturning, AtAfterThrowing
    5. }

    获取 注解的value值,通常返回的是 标记有 @Pointcut 注解的 方法名

    1. Method method = annotation.annotationType().getDeclaredMethod(attributeName);
    2. ReflectionUtils.makeAccessible(method);
    3. return method.invoke(annotation);

    开始包装该切面方法:

    关键代码块

    1. switch (aspectJAnnotation.getAnnotationType()) {
    2. case AtPointcut:
    3. if (logger.isDebugEnabled()) {
    4. logger.debug("Processing pointcut '" + candidateAdviceMethod.getName() + "'");
    5. }
    6. return null;
    7. case AtAround:
    8. springAdvice = new AspectJAroundAdvice(
    9. candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
    10. break;
    11. case AtBefore:
    12. springAdvice = new AspectJMethodBeforeAdvice(
    13. candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
    14. break;
    15. case AtAfter:
    16. springAdvice = new AspectJAfterAdvice(
    17. candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
    18. break;
    19. case AtAfterReturning:
    20. springAdvice = new AspectJAfterReturningAdvice(
    21. candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
    22. AfterReturning afterReturningAnnotation = (AfterReturning) aspectJAnnotation.getAnnotation();
    23. if (StringUtils.hasText(afterReturningAnnotation.returning())) {
    24. springAdvice.setReturningName(afterReturningAnnotation.returning());
    25. }
    26. break;
    27. case AtAfterThrowing:
    28. springAdvice = new AspectJAfterThrowingAdvice(
    29. candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
    30. AfterThrowing afterThrowingAnnotation = (AfterThrowing) aspectJAnnotation.getAnnotation();
    31. if (StringUtils.hasText(afterThrowingAnnotation.throwing())) {
    32. springAdvice.setThrowingName(afterThrowingAnnotation.throwing());
    33. }
    34. break;
    35. default:
    36. throw new UnsupportedOperationException(
    37. "Unsupported advice type on method: " + candidateAdviceMethod);
    38. }

    根据切面的类型,返回不同的Advice类型的对象。

    org.springframework.aop.aspectj.AbstractAspectJAdvice

    再包装成Advisor

    org.springframework.aop.aspectj.annotation.InstantiationModelAwarePointcutAdvisorImpl

    寻找可以应用在当前bean的 advisor。这个逻辑有点复杂,先跳过

    return canApply(pca.getPointcut(), targetClass, hasIntroductions);

    接下来就是创建代理对象

    1. protected Object createProxy(Class beanClass, @Nullable String beanName,
    2. @Nullable Object[] specificInterceptors, TargetSource targetSource) {
    3. if (this.beanFactory instanceof ConfigurableListableBeanFactory) {
    4. AutoProxyUtils.exposeTargetClass((ConfigurableListableBeanFactory) this.beanFactory, beanName, beanClass);
    5. }
    6. ProxyFactory proxyFactory = new ProxyFactory();
    7. proxyFactory.copyFrom(this);
    8. if (!proxyFactory.isProxyTargetClass()) {
    9. if (shouldProxyTargetClass(beanClass, beanName)) {
    10. proxyFactory.setProxyTargetClass(true);
    11. }
    12. else {
    13. evaluateProxyInterfaces(beanClass, proxyFactory);
    14. }
    15. }
    16. Advisor[] advisors = buildAdvisors(beanName, specificInterceptors);
    17. proxyFactory.addAdvisors(advisors);
    18. proxyFactory.setTargetSource(targetSource);
    19. customizeProxyFactory(proxyFactory);
    20. proxyFactory.setFrozen(this.freezeProxy);
    21. if (advisorsPreFiltered()) {
    22. proxyFactory.setPreFiltered(true);
    23. }
    24. return proxyFactory.getProxy(getProxyClassLoader());
    25. }

    evaluateProxyInterfaces(beanClass, proxyFactory);

    这里会提取 目前代理对象的 接口

    Advisor[] advisors = buildAdvisors(beanName, specificInterceptors);

    将 接口 转为 Advisor 类型

    1. 如果是 Advisor 直接返回

    if (adviceObject instanceof Advisor) {
    return (Advisor) adviceObject;
    }

    2. MethodInterceptor

    if (advice instanceof MethodInterceptor) {
    // So well-known it doesn't even need an adapter.
    return new DefaultPointcutAdvisor(advice);
    }

    3. 其他类型

    MethodBeforeAdvice  MethodBeforeAdviceAdapter

    AfterReturningAdvice  AfterReturningAdviceAdapter

    ThrowsAdvice ThrowsAdviceAdapter

    for (AdvisorAdapter adapter : this.adapters) {
    // Check that it is supported.
    if (adapter.supportsAdvice(advice)) {
    return new DefaultPointcutAdvisor(advice);
    }
    }

    这里由个疑问,上述都是找的 Advisor 类型,为什么还有 不是Advisor的?

    1. public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
    2. if (config.isOptimize() || config.isProxyTargetClass() || hasNoUserSuppliedProxyInterfaces(config)) {
    3. Class targetClass = config.getTargetClass();
    4. if (targetClass == null) {
    5. throw new AopConfigException("TargetSource cannot determine target class: " +
    6. "Either an interface or a target is required for proxy creation.");
    7. }
    8. if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) {
    9. return new JdkDynamicAopProxy(config);
    10. }
    11. return new ObjenesisCglibAopProxy(config);
    12. }
    13. else {
    14. return new JdkDynamicAopProxy(config);
    15. }
    16. }

    这边代码看起来绕来绕去,实际设计的比较精炼。使用一个工厂类的一个方法就返回了代理对象。

    proxyFactory.getProxy(getProxyClassLoader());

    createAopProxy().getProxy(classLoader)

    getAopProxyFactory().createAopProxy(this)

    多个方法级联调用,只是这里进行了 一个拆分。

    1. public JdkDynamicAopProxy(AdvisedSupport config) throws AopConfigException {
    2. Assert.notNull(config, "AdvisedSupport must not be null");
    3. if (config.getAdvisors().length == 0 && config.getTargetSource() == AdvisedSupport.EMPTY_TARGET_SOURCE) {
    4. throw new AopConfigException("No advisors and no TargetSource specified");
    5. }
    6. this.advised = config;
    7. }

    上面描述了,JdkDynamicAopProxy就是 InvocationHandler的实现类。

    Class[] proxiedInterfaces = AopProxyUtils.completeProxiedInterfaces(this.advised, true);

    这里会获取需要代理类实现的接口。然后使用JDK提供的代理生成方法获取代理示例 。

    如果是 cglib完成代理生成,

    enhancer.setSuperclass(proxySuperClass);
    enhancer.setInterfaces(AopProxyUtils.completeProxiedInterfaces(this.advised));

    其invoke方法内部 List chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass); 完了对切面的执行调用。

    执行过程:

    AspectJAroundAdvice

    public Object invoke(MethodInvocation mi) throws Throwable {
    if (!(mi instanceof ProxyMethodInvocation)) {
    throw new IllegalStateException("MethodInvocation is not a Spring ProxyMethodInvocation: " + mi);
    }
    ProxyMethodInvocation pmi = (ProxyMethodInvocation) mi;
    ProceedingJoinPoint pjp = lazyGetProceedingJoinPoint(pmi);
    JoinPointMatch jpm = getJoinPointMatch(pmi);
    return invokeAdviceMethod(pjp, jpm, null, null);
    }

     

    AspectJAfterAdvice

    public Object invoke(MethodInvocation mi) throws Throwable {
    try {
    return mi.proceed();
    }
    finally {
    invokeAdviceMethod(getJoinPointMatch(), null, null);
    }
    }

    AspectJAfterReturningAdvice 由 AfterReturningAdviceInterceptor包装,

    public Object invoke(MethodInvocation mi) throws Throwable {
    Object retVal = mi.proceed();
    invokeAdviceMethod(getJoinPointMatch(), returnValue, null);
    return retVal;
    }

    AspectJAfterThrowingAdvice

    public Object invoke(MethodInvocation mi) throws Throwable {
    try {
    return mi.proceed();
    }
    catch (Throwable ex) {
    if (shouldInvokeOnThrowing(ex)) {
    invokeAdviceMethod(getJoinPointMatch(), null, ex);
    }
    throw ex;
    }
    }

    AspectJMethodBeforeAdvice,由MethodBeforeAdviceInterceptor包装

    public Object invoke(MethodInvocation mi) throws Throwable {
    invokeAdviceMethod(getJoinPointMatch(), null, null);
    return mi.proceed();
    }

    invokeAdviceMethod 方法就是调用 切面方法

    mi.proceed()  就是执行下一个切面方法

    第一个问题,advice的执行顺序是什么?

         每个advice 需要实现 org.springframework.core.Ordered接口,用于指定排序

    第二个问题,什么时候执行业务方法?

    if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {
         return invokeJoinpoint();
    }

    protected Object invokeJoinpoint() throws Throwable {
         return AopUtils.invokeJoinpointUsingReflection(this.target, this.method, this.arguments);
    }

    当所有Advice都调用后,会执行业务方法。

  • 相关阅读:
    面试题 17.08. 马戏团人塔
    2022-11-30 mysql-Tuning InnoDB Primary Keys
    python基于PHP+MySQL的综合排课系统
    java计算机毕业设计租车管理系统源码+mysql数据库+系统+部署+lw文档
    (附源码)spring boot基于微信小程序的口腔诊所预约系统 毕业设计 201738
    boot+mp搭建版本踩坑记录
    etcd入门
    将用友U8的数据可视化需要哪些工具?
    pycharm连接MySql数据库,新建表creat table、删除表drop table、查询表select、插入数据insert
    持续集成与持续交付
  • 原文地址:https://blog.csdn.net/htydowd/article/details/140035317