美文网首页
初识AOP:Spring AOP框架

初识AOP:Spring AOP框架

作者: overflowedstack | 来源:发表于2020-04-25 16:39 被阅读0次

初识AOP

  1. AOP基本概念
    AOP,Aspect Oriented Programming,面向切面的编程,将一些分散在对象或者类中的与业务逻辑无关的代码分离出来进行独立的管理编码。

  2. AOP相关术语

  • 连接点(Join Point)
    类中的方法,不管有没有被抽取共性功能。

  • 切入点(Pointcut)
    指被抽取了共性功能的方法。
    切入点一定是连接点,连接点不一定是切入点。

  • 通知(Advice)
    抽取的共性功能组成的代码。通知方法放在通知类里。
    通知有位置之分。

  • 引入(Introduction) - 很少用到,了解即可
    为类添加额外的成员变量或者成员方法。

  • 目标对象(Target object)
    缺少完整业务代码的方法,所在的对象。不能完整执行。
    即包含切入点的对象。

  • 代理对象
    代理目标对象,将通知加到代理对象的方法中。

  • 织入(Weaving)
    将通知加入到切入点对应的位置。

  • 切面(Aspect)
    切入点和通知之间的关系。

  1. AOP现有两个主要的流行框架
    即AspectJ和Spring AOP。

Aspectj 框架

Aspectj框架是静态代理的代表,它有自己的编译器,在编译期间就生成了class文件完成了代理。这里就不具体研究了。

Spring AOP

  1. 相关jar包
  • spring-aop-5.1.8.RELEASE.jar
    Spring自身的AOP包,就包含在spring的包中,它要和AOP联盟的包配合使用
  • com.springsource.org.aopalliance-1.0.0.jar
    AOP联盟规范,第三方jar包
  • spring-aspects-5.1.8.RELEASE.jar
    Spring整合aspectj的包,要与第三方切面的包成对使用
  • aspectjweaver-1.9.4.jar
    第三方切面的包

为什么Spring AOP会用到aspectj的包呢?那是因为Spring沿用了aspectj的注解,关于切点的解析和匹配使用了aspectj的内容。
不过AOP本身还是纯粹的Spring AOP。

  1. Spring AOP Demo (代理实现了接口的bean)
package io.github.dunwu.spring.core.aop.example;

import java.lang.reflect.Proxy;

import org.aopalliance.aop.Advice;
import org.springframework.aop.Advisor;
import org.springframework.aop.SpringProxy;
import org.springframework.aop.framework.Advised;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.core.DecoratingProxy;

public class AnnotationIOCDemo {
    public static void main (String args[]) throws InterruptedException{
        //System.getProperties().put("jdk.proxy.ProxyGenerator.saveGeneratedFiles", "true");
        System.getProperties().put("sun.misc.ProxyGenerator.saveGeneratedFiles", "true");
        
        ApplicationContext context = new AnnotationConfigApplicationContext("io.github.dunwu.spring.core.aop.example");
        
        IOCService iocService= (IOCService) context.getBean("IOCServiceImpl");
        
        iocService.hollo();
        
//        Proxy iocService0= (Proxy) context.getBean("IOCServiceImpl");
//        
//        SpringProxy iocService1= (SpringProxy) context.getBean("IOCServiceImpl");
//        
//        Advised iocService2= (Advised) context.getBean("IOCServiceImpl");
//        Advisor[] advisors = iocService2.getAdvisors();
//        Advisor advisor = advisors[1];
//        
//        System.out.println("test");
//        
//        iocService2.removeAdvice(advisor.getAdvice());
//        
//        iocService.hollo();
//        
//        DecoratingProxy iocService3= (DecoratingProxy) context.getBean("IOCServiceImpl");
//        Class clz = iocService3.getDecoratedClass();
        
        //Thread.sleep(6000000);
    }
}
  1. 底层原理
    3.1 来看看IocServiceImpl这个bean的创建过程。
  • 创建instance,得到了一个IocServiceImpl类型的实例。一切正常。
  • populateBean,注入依赖。一切正常。
  • initilizeBean,前方高能!!!AbstractAutowireCapableBeanFactory这里会调bean的初始化后后置处理器。
    其中一个后置处理器叫作AnnotationAwareAspectJAutoProxyCreator,重点关注
    public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)
            throws BeansException {

        Object result = existingBean;
        for (BeanPostProcessor processor : getBeanPostProcessors()) {
            Object current = processor.postProcessAfterInitialization(result, beanName);
            if (current == null) {
                return result;
            }
            result = current;
        }
        return result;
    }
  • 这个后置处理器会调用wrapIfNecessary方法,用createProxy方法来创建代理对象。
        // Create proxy if we have advice.
        Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
        if (specificInterceptors != DO_NOT_PROXY) {
            this.advisedBeans.put(cacheKey, Boolean.TRUE);
            Object proxy = createProxy(
                    bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
            this.proxyTypes.put(cacheKey, proxy.getClass());
            return proxy;
        }
  • 而createProxy时,会调用如下createAopProxy方法,根据是否有接口,选择创建Jdk代理或者Cglib代理。
    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);
        }
    }
  • createAopProxy完成后,回到createProxy方法,调用Proxy.newProxyInstance。而这段代码,在上一篇动态代理里研究过,它就是根据InvocationHandler,将方法的增强织入到代理对象的过程。
Proxy.newProxyInstance(classLoader, proxiedInterfaces, this);
    public static Object newProxyInstance(ClassLoader loader,
                                          Class<?>[] interfaces,
                                          InvocationHandler h) {
        Objects.requireNonNull(h);

        final Class<?> caller = System.getSecurityManager() == null
                                    ? null
                                    : Reflection.getCallerClass();

        /*
         * Look up or generate the designated proxy class and its constructor.
         */
        Constructor<?> cons = getProxyConstructor(caller, loader, interfaces);

        return newProxyInstance(caller, cons, h);
    }
  • 最后,就得到了名为$Proxy20的代理对象。

3.2 且慢!此时,小小的脑袋中还是有大大的问号。
Spring是如何知道哪些切点的?
Advice方法是如何被加载到容器中的?
Spring是如何将通知方法织入切点的?
通知方法的执行顺序是如何决定的?

好,二话不说看代码。

3.3 创建Advisor,以及PointCut
在创建bean的过程中,会调用findEligibleAdvisors。其中,会将切点的表达式与该bean进行匹配,判断是否是符合切点规定的被代理类。

MethodMatcher methodMatcher = pc.getMethodMatcher();
    private List<Method> getAdvisorMethods(Class<?> aspectClass) {
        final List<Method> methods = new ArrayList<>();
        ReflectionUtils.doWithMethods(aspectClass, method -> {
            // Exclude pointcuts
            if (AnnotationUtils.getAnnotation(method, Pointcut.class) == null) {
                methods.add(method);
            }
        });
        methods.sort(METHOD_COMPARATOR);
        return methods;
    }

其中,排序是依据以下定义做比较:(后面还会再做下一种排序)

    private static final Comparator<Method> METHOD_COMPARATOR;

    static {
        Comparator<Method> adviceKindComparator = new ConvertingComparator<>(
                new InstanceComparator<>(
                        Around.class, Before.class, After.class, AfterReturning.class, AfterThrowing.class),
                (Converter<Method, Annotation>) method -> {
                    AspectJAnnotation<?> annotation =
                        AbstractAspectJAdvisorFactory.findAspectJAnnotationOnMethod(method);
                    return (annotation != null ? annotation.getAnnotation() : null);
                });
        Comparator<Method> methodNameComparator = new ConvertingComparator<>(Method::getName);
        METHOD_COMPARATOR = adviceKindComparator.thenComparing(methodNameComparator);
    }
Advisor advisor = getAdvisor(method, lazySingletonAspectInstanceFactory, advisors.size(), aspectName);
    @Nullable
    private AspectJExpressionPointcut getPointcut(Method candidateAdviceMethod, Class<?> candidateAspectClass) {
        AspectJAnnotation<?> aspectJAnnotation =
                AbstractAspectJAdvisorFactory.findAspectJAnnotationOnMethod(candidateAdviceMethod);
        if (aspectJAnnotation == null) {
            return null;
        }

        AspectJExpressionPointcut ajexp =
                new AspectJExpressionPointcut(candidateAspectClass, new String[0], new Class<?>[0]);
        ajexp.setExpression(aspectJAnnotation.getPointcutExpression());
        if (this.beanFactory != null) {
            ajexp.setBeanFactory(this.beanFactory);
        }
        return ajexp;
    }

3.4 获取通知方法,并对通知方法进行排序。

    protected List<Advisor> findEligibleAdvisors(Class<?> beanClass, String beanName) {
        List<Advisor> candidateAdvisors = findCandidateAdvisors();
        List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);
        extendAdvisors(eligibleAdvisors);
        if (!eligibleAdvisors.isEmpty()) {
            eligibleAdvisors = sortAdvisors(eligibleAdvisors);
        }
        return eligibleAdvisors;
    }

sortAdvisors对通知方法再次进行了排序。同一个切面中,如果有after通知,那么after具有最高的权重。如下:

    private int comparePrecedenceWithinAspect(Advisor advisor1, Advisor advisor2) {
        boolean oneOrOtherIsAfterAdvice =
                (AspectJAopUtils.isAfterAdvice(advisor1) || AspectJAopUtils.isAfterAdvice(advisor2));
        int adviceDeclarationOrderDelta = getAspectDeclarationOrder(advisor1) - getAspectDeclarationOrder(advisor2);

        if (oneOrOtherIsAfterAdvice) {
            // the advice declared last has higher precedence
            if (adviceDeclarationOrderDelta < 0) {
                // advice1 was declared before advice2
                // so advice1 has lower precedence
                return LOWER_PRECEDENCE;
            }
            else if (adviceDeclarationOrderDelta == 0) {
                return SAME_PRECEDENCE;
            }
            else {
                return HIGHER_PRECEDENCE;
            }
        }
        else {
            // the advice declared first has higher precedence
            if (adviceDeclarationOrderDelta < 0) {
                // advice1 was declared before advice2
                // so advice1 has higher precedence
                return HIGHER_PRECEDENCE;
            }
            else if (adviceDeclarationOrderDelta == 0) {
                return SAME_PRECEDENCE;
            }
            else {
                return LOWER_PRECEDENCE;
            }
        }
    }

组合所有的增强器:

    protected Advisor[] buildAdvisors(@Nullable String beanName, @Nullable Object[] specificInterceptors) {
        // Handle prototypes correctly...
        Advisor[] commonInterceptors = resolveInterceptorNames();

        List<Object> allInterceptors = new ArrayList<>();
        if (specificInterceptors != null) {
            allInterceptors.addAll(Arrays.asList(specificInterceptors));
            if (commonInterceptors.length > 0) {
                if (this.applyCommonInterceptorsFirst) {
                    allInterceptors.addAll(0, Arrays.asList(commonInterceptors));
                }
                else {
                    allInterceptors.addAll(Arrays.asList(commonInterceptors));
                }
            }
        }
        if (logger.isTraceEnabled()) {
            int nrOfCommonInterceptors = commonInterceptors.length;
            int nrOfSpecificInterceptors = (specificInterceptors != null ? specificInterceptors.length : 0);
            logger.trace("Creating implicit proxy for bean '" + beanName + "' with " + nrOfCommonInterceptors +
                    " common interceptors and " + nrOfSpecificInterceptors + " specific interceptors");
        }

        Advisor[] advisors = new Advisor[allInterceptors.size()];
        for (int i = 0; i < allInterceptors.size(); i++) {
            advisors[i] = this.advisorAdapterRegistry.wrap(allInterceptors.get(i));
        }
        return advisors;
    }

引用一张调用图:


加载切点及通知方法
注意!

关于同一个切面内,多个通知方法的顺序,本文的例子是基于注解进行研究的。基于注解的话,执行顺序为around -> before -> target method -> around -> after.
如果是基于xml,配置多个通知方法,多个前置通知方法,和多个后置通知方法,是依照xml里定义的顺序来执行的。
也就是说,基于注解,和基于xml,多个通知方法的执行顺序是不一致的。
关于这一点,查看spring官方文档,发现spring本身就说了,它不保证这种情况下的通知方法执行顺序。要么你尽量把多个通知方法合并成一个通知,要么,就把多个通知方法放进不同的切面,再在切面的级别上显式指定order。

When two pieces of advice defined in the same aspect both need to run at the same join point, the ordering is undefined (since there is no way to retrieve the declaration order through reflection for javac-compiled classes). Consider collapsing such advice methods into one advice method per join point in each aspect class or refactor the pieces of advice into separate aspect classes that you can order at the aspect level.

3.5 调用被代理的目标方法时,是如何进行增强的
调用invoke方法。其中,retVal = invocation.proceed();会调用拦截方法链,依次调用各个拦截方法。

    /**
     * Implementation of {@code InvocationHandler.invoke}.
     * <p>Callers will see exactly the exception thrown by the target,
     * unless a hook method throws an exception.
     */
    @Override
    @Nullable
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        MethodInvocation invocation;
        Object oldProxy = null;
        boolean setProxyContext = false;

        TargetSource targetSource = this.advised.targetSource;
        Object target = null;

        try {
            if (!this.equalsDefined && AopUtils.isEqualsMethod(method)) {
                // The target does not implement the equals(Object) method itself.
                return equals(args[0]);
            }
            else if (!this.hashCodeDefined && AopUtils.isHashCodeMethod(method)) {
                // The target does not implement the hashCode() method itself.
                return hashCode();
            }
            else if (method.getDeclaringClass() == DecoratingProxy.class) {
                // There is only getDecoratedClass() declared -> dispatch to proxy config.
                return AopProxyUtils.ultimateTargetClass(this.advised);
            }
            else if (!this.advised.opaque && method.getDeclaringClass().isInterface() &&
                    method.getDeclaringClass().isAssignableFrom(Advised.class)) {
                // Service invocations on ProxyConfig with the proxy config...
                return AopUtils.invokeJoinpointUsingReflection(this.advised, method, args);
            }

            Object retVal;

            if (this.advised.exposeProxy) {
                // Make invocation available if necessary.
                oldProxy = AopContext.setCurrentProxy(proxy);
                setProxyContext = true;
            }

            // Get as late as possible to minimize the time we "own" the target,
            // in case it comes from a pool.
            target = targetSource.getTarget();
            Class<?> targetClass = (target != null ? target.getClass() : null);

            // Get the interception chain for this method.
            List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);

            // Check whether we have any advice. If we don't, we can fallback on direct
            // reflective invocation of the target, and avoid creating a MethodInvocation.
            if (chain.isEmpty()) {
                // We can skip creating a MethodInvocation: just invoke the target directly
                // Note that the final invoker must be an InvokerInterceptor so we know it does
                // nothing but a reflective operation on the target, and no hot swapping or fancy proxying.
                Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);
                retVal = AopUtils.invokeJoinpointUsingReflection(target, method, argsToUse);
            }
            else {
                // We need to create a method invocation...
                invocation = new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain);
                // Proceed to the joinpoint through the interceptor chain.
                retVal = invocation.proceed();
            }

            // Massage return value if necessary.
            Class<?> returnType = method.getReturnType();
            if (retVal != null && retVal == target &&
                    returnType != Object.class && returnType.isInstance(proxy) &&
                    !RawTargetAccess.class.isAssignableFrom(method.getDeclaringClass())) {
                // Special case: it returned "this" and the return type of the method
                // is type-compatible. Note that we can't help if the target sets
                // a reference to itself in another returned object.
                retVal = proxy;
            }
            else if (retVal == null && returnType != Void.TYPE && returnType.isPrimitive()) {
                throw new AopInvocationException(
                        "Null return value from advice does not match primitive return type for: " + method);
            }
            return retVal;
        }
        finally {
            if (target != null && !targetSource.isStatic()) {
                // Must have come from TargetSource.
                targetSource.releaseTarget(target);
            }
            if (setProxyContext) {
                // Restore old proxy.
                AopContext.setCurrentProxy(oldProxy);
            }
        }
    }

首先,会调用ReflectiveMethodInvocation.proceed()方法。方法的一开始会比较currentInterceptorIndex与this.interceptorsAndDynamicMethodMatchers.size() - 1的大小。currentInterceptorIndex的初始值是-1,每处理一个Inteceptor就会自增。最后两者相等,就说明interceptor处理完了,可以使用invokeJointpoint调用真实目标对象的方法了。

    public Object proceed() throws Throwable {
        //  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);
        }
    }

接下来,调用AspectJAfterAdvice的invoke方法。由于是after通知,所以先往前调用剩下的拦截方法,最后finally再调用自身的invokeAdviceMethod。

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

下一个调用的是AspectJAroundAdvice.invoke方法。它就有点不一样了。它直接调用了自身的invokeAdviceMethod。

    @Override
    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);
    }

追踪到这个方法,invoke了我们自己定义的around增强方法。

    protected Object invokeAdviceMethodWithGivenArgs(Object[] args) throws Throwable {
        Object[] actualArgs = args;
        if (this.aspectJAdviceMethod.getParameterCount() == 0) {
            actualArgs = null;
        }
        try {
            ReflectionUtils.makeAccessible(this.aspectJAdviceMethod);
            // TODO AopUtils.invokeJoinpointUsingReflection
            return this.aspectJAdviceMethod.invoke(this.aspectInstanceFactory.getAspectInstance(), actualArgs);
        }
        catch (IllegalArgumentException ex) {
            throw new AopInvocationException("Mismatch on arguments to advice method [" +
                    this.aspectJAdviceMethod + "]; pointcut expression [" +
                    this.pointcut.getPointcutExpression() + "]", ex);
        }
        catch (InvocationTargetException ex) {
            throw ex.getTargetException();
        }
    }

而在这个around方法里,先执行了前半部分around,到了p.proceed()时,它又在当前拦截链的基础上,继续往下调用剩下的拦截方法。

    @Around("testAOP()")
    public Object around(ProceedingJoinPoint p){
        System.out.println("around before testAOP...");
        Object o = null;
        try {
            o = p.proceed();
        } catch (Throwable e) {
            e.printStackTrace();
        }
        System.out.println("around after testAOP...");
        return o;
    }

于是,程序又获取了最后一个拦截方法before方法。MethodBeforeAdviceInterceptor.invoke方法,在第一行,就直接调用了before方法的主体内容。

    @Override
    public Object invoke(MethodInvocation mi) throws Throwable {
        this.advice.before(mi.getMethod(), mi.getArguments(), mi.getThis());
        return mi.proceed();
    }

它的第二行mi.proceed(),又调用了ReflectiveMethodInvocation.proceed()方法,当进行this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1判断时,这时,它们相等了。于是,invokeJoinpoint()内部就会通过反射机制调用真实对象的目标方法。

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

真实对象的目标方法调用结束后,会return到around通知方法的中间,继续完成剩下的around增强。而around通知完成之后,会return,走到invoke after通知方法的地方。
至此,整个通知方法拦截链就执行完成了。

  1. Spring aop中,jdk动态代理生成的代理对象
    4.1 将动态生成的代理对象存到硬盘,通过反编译工具,查看具体代码。
    部分摘要如下,完整内容见附录。
    会发现代理对象继承了Proxy类,并实现了IOCService, SpringProxy, Advised, DecoratingProxy这四个接口。
public final class $Proxy20 extends Proxy implements IOCService, SpringProxy, Advised, DecoratingProxy {

  public $Proxy20(InvocationHandler paramInvocationHandler) {
    super(paramInvocationHandler);
  }

  public final void addAdvisor(Advisor paramAdvisor) throws AopConfigException {
    try {
      this.h.invoke(this, m20, new Object[] { paramAdvisor });
      return;
    } catch (Error|RuntimeException error) {
      throw null;
    } catch (Throwable throwable) {
      throw new UndeclaredThrowableException(throwable);
    } 
  }

  public final void removeAdvisor(int paramInt) throws AopConfigException {
    try {
      this.h.invoke(this, m21, new Object[] { Integer.valueOf(paramInt) });
      return;
    } catch (Error|RuntimeException error) {
      throw null;
    } catch (Throwable throwable) {
      throw new UndeclaredThrowableException(throwable);
    } 
  }

  public final void addAdvice(int paramInt, Advice paramAdvice) throws AopConfigException {
    try {
      this.h.invoke(this, m14, new Object[] { Integer.valueOf(paramInt), paramAdvice });
      return;
    } catch (Error|RuntimeException error) {
      throw null;
    } catch (Throwable throwable) {
      throw new UndeclaredThrowableException(throwable);
    } 
  }

  public final boolean removeAdvice(Advice paramAdvice) {
    try {
      return ((Boolean)this.h.invoke(this, m24, new Object[] { paramAdvice })).booleanValue();
    } catch (Error|RuntimeException error) {
      throw null;
    } catch (Throwable throwable) {
      throw new UndeclaredThrowableException(throwable);
    } 
  }

  public final String hollo() {
    try {
      return (String)this.h.invoke(this, m3, null);
    } catch (Error|RuntimeException error) {
      throw null;
    } catch (Throwable throwable) {
      throw new UndeclaredThrowableException(throwable);
    } 
  }
}

4.2 SpringProxy接口
看注释,SpringProxy接口被所有的AOP代理对象实现。它用来标志对象是否是Spring生成的代理对象。

/**
 * Marker interface implemented by all AOP proxies. Used to detect
 * whether or not objects are Spring-generated proxies.
 * @see org.springframework.aop.support.AopUtils#isAopProxy(Object)
 */
public interface SpringProxy {

}

例如,AopUtils的isAopProxy方法就用了instanceof SpringProxy来做判断。

    public static boolean isAopProxy(@Nullable Object object) {
        return (object instanceof SpringProxy &&
                (Proxy.isProxyClass(object.getClass()) || ClassUtils.isCglibProxyClass(object.getClass())));
    }

4.3 Advised接口
继续看注释,注释是个好东西。Advised接口维护了AOP代理的配置信息,例如拦截方法。另外,它还提供了方法可以在运行时给我们的代理对象添加和删除Advisor/Advise。

/**
 * Interface to be implemented by classes that hold the configuration
 * of a factory of AOP proxies. This configuration includes the
 * Interceptors and other advice, Advisors, and the proxied interfaces.
 *
 * <p>Any AOP proxy obtained from Spring can be cast to this interface to
 * allow manipulation of its AOP advice.

Advised,Advice与Advisor

  • Advised: 包含所有的Advisor 和 Advice
  • Advice: 通知拦截器
  • Advisor: 通知 + 切入点的适配器

4.4 DecoratingProxy接口
这个接口只定义了一个方法,用来返回被代理对象。

public interface DecoratingProxy {
    /**
     * Return the (ultimate) decorated class behind this proxy.
     * <p>In case of an AOP proxy, this will be the ultimate target class,
     * not just the immediate target (in case of multiple nested proxies).
     * @return the decorated class (never {@code null})
     */
    Class<?> getDecoratedClass();
}
  1. Spring AOP Demo (CGLIB, 代理普通的bean,没有实现接口)
    上面是对基于接口的类的aop,用了spring jdk动态代理技术。
    接下来对demo稍作修改,不实现接口,直接对一个普通的bean做aop,会用到cglib来进行动态代理。
    用如下方式将代理类存到硬盘:
System.setProperty(DebuggingClassWriter.DEBUG_LOCATION_PROPERTY, "/Users/a123/Documents/git/spring-tutorial/spring-tutorial-core/spring-tutorial-core-ioc");
  1. Spring AOP 显式指定用CGLIB动态代理
    @EnableAspectJAutoProxy(proxyTargetClass=true)
  • proxyTargetClass:这个属性为true时,目标类本身被代理而不是目标类的接口。如果这个属性值被设为true,CGLIB代理将被创建。
  • optimize:用来控制通过CGLIB创建的代理是否使用激进的优化策略。 除非完全了解AOP代理如何处理优化,否则不推荐用户使用这个设置。目前这个属性仅用于CGLIB代理; 对于JDK动态代理(缺省代理)无效。

附录
demo class:

import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.EnableAspectJAutoProxy;

@EnableAspectJAutoProxy
@Configuration
public class AnnotationConfig {
}
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;

@Aspect
@Component
public class AspectJTest {

    @Pointcut("execution(public * io.github.dunwu.spring.core.aop.example.IOCServiceImpl.hollo(..))")
    public void testAOP(){
    }

    @Before("testAOP()")
    public void before(){
        System.out.println("before testAOP...");
    }

    @After("testAOP()")
    public void after(){
        System.out.println("after testAOP...");
    }

    @Around("testAOP()")
    public Object around(ProceedingJoinPoint p){
        System.out.println("around before testAOP...");
        Object o = null;
        try {
            o = p.proceed();
        } catch (Throwable e) {
            e.printStackTrace();
        }
        System.out.println("around after testAOP...");
        return o;
    }
}
public interface IOCService {
    public String hollo();
}
import org.springframework.stereotype.Component;

@Component
public class IOCServiceImpl implements IOCService {
    public String hollo() {
            System.out.println("Hello,IOC");
        return "Hello,IOC";
    }
}

Spring AOP中,jdk动态代理生成的代理类:

package com.sun.proxy;

import io.github.dunwu.spring.core.aop.example.IOCService;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.lang.reflect.UndeclaredThrowableException;
import org.aopalliance.aop.Advice;
import org.springframework.aop.Advisor;
import org.springframework.aop.SpringProxy;
import org.springframework.aop.TargetSource;
import org.springframework.aop.framework.Advised;
import org.springframework.aop.framework.AopConfigException;
import org.springframework.core.DecoratingProxy;

public final class $Proxy20 extends Proxy implements IOCService, SpringProxy, Advised, DecoratingProxy {
  private static Method m1;
  
  private static Method m12;
  
  private static Method m20;
  
  private static Method m9;
  
  private static Method m21;
  
  private static Method m17;
  
  private static Method m4;
  
  private static Method m8;
  
  private static Method m14;
  
  private static Method m15;
  
  private static Method m0;
  
  private static Method m18;
  
  private static Method m24;
  
  private static Method m11;
  
  private static Method m3;
  
  private static Method m7;
  
  private static Method m2;
  
  private static Method m26;
  
  private static Method m19;
  
  private static Method m27;
  
  private static Method m22;
  
  private static Method m5;
  
  private static Method m6;
  
  private static Method m23;
  
  private static Method m10;
  
  private static Method m25;
  
  private static Method m13;
  
  private static Method m16;
  
  public $Proxy20(InvocationHandler paramInvocationHandler) {
    super(paramInvocationHandler);
  }
  
  public final boolean equals(Object paramObject) {
    try {
      return ((Boolean)this.h.invoke(this, m1, new Object[] { paramObject })).booleanValue();
    } catch (Error|RuntimeException error) {
      throw null;
    } catch (Throwable throwable) {
      throw new UndeclaredThrowableException(throwable);
    } 
  }
  
  public final boolean isExposeProxy() {
    try {
      return ((Boolean)this.h.invoke(this, m12, null)).booleanValue();
    } catch (Error|RuntimeException error) {
      throw null;
    } catch (Throwable throwable) {
      throw new UndeclaredThrowableException(throwable);
    } 
  }
  
  public final void addAdvisor(Advisor paramAdvisor) throws AopConfigException {
    try {
      this.h.invoke(this, m20, new Object[] { paramAdvisor });
      return;
    } catch (Error|RuntimeException error) {
      throw null;
    } catch (Throwable throwable) {
      throw new UndeclaredThrowableException(throwable);
    } 
  }
  
  public final boolean isProxyTargetClass() {
    try {
      return ((Boolean)this.h.invoke(this, m9, null)).booleanValue();
    } catch (Error|RuntimeException error) {
      throw null;
    } catch (Throwable throwable) {
      throw new UndeclaredThrowableException(throwable);
    } 
  }
  
  public final void removeAdvisor(int paramInt) throws AopConfigException {
    try {
      this.h.invoke(this, m21, new Object[] { Integer.valueOf(paramInt) });
      return;
    } catch (Error|RuntimeException error) {
      throw null;
    } catch (Throwable throwable) {
      throw new UndeclaredThrowableException(throwable);
    } 
  }
  
  public final Class[] getProxiedInterfaces() {
    try {
      return (Class[])this.h.invoke(this, m17, null);
    } catch (Error|RuntimeException error) {
      throw null;
    } catch (Throwable throwable) {
      throw new UndeclaredThrowableException(throwable);
    } 
  }
  
  public final int indexOf(Advisor paramAdvisor) {
    try {
      return ((Integer)this.h.invoke(this, m4, new Object[] { paramAdvisor })).intValue();
    } catch (Error|RuntimeException error) {
      throw null;
    } catch (Throwable throwable) {
      throw new UndeclaredThrowableException(throwable);
    } 
  }
  
  public final TargetSource getTargetSource() {
    try {
      return (TargetSource)this.h.invoke(this, m8, null);
    } catch (Error|RuntimeException error) {
      throw null;
    } catch (Throwable throwable) {
      throw new UndeclaredThrowableException(throwable);
    } 
  }
  
  public final void addAdvice(int paramInt, Advice paramAdvice) throws AopConfigException {
    try {
      this.h.invoke(this, m14, new Object[] { Integer.valueOf(paramInt), paramAdvice });
      return;
    } catch (Error|RuntimeException error) {
      throw null;
    } catch (Throwable throwable) {
      throw new UndeclaredThrowableException(throwable);
    } 
  }
  
  public final void addAdvice(Advice paramAdvice) throws AopConfigException {
    try {
      this.h.invoke(this, m15, new Object[] { paramAdvice });
      return;
    } catch (Error|RuntimeException error) {
      throw null;
    } catch (Throwable throwable) {
      throw new UndeclaredThrowableException(throwable);
    } 
  }
  
  public final int hashCode() {
    try {
      return ((Integer)this.h.invoke(this, m0, null)).intValue();
    } catch (Error|RuntimeException error) {
      throw null;
    } catch (Throwable throwable) {
      throw new UndeclaredThrowableException(throwable);
    } 
  }
  
  public final boolean isInterfaceProxied(Class paramClass) {
    try {
      return ((Boolean)this.h.invoke(this, m18, new Object[] { paramClass })).booleanValue();
    } catch (Error|RuntimeException error) {
      throw null;
    } catch (Throwable throwable) {
      throw new UndeclaredThrowableException(throwable);
    } 
  }
  
  public final boolean removeAdvice(Advice paramAdvice) {
    try {
      return ((Boolean)this.h.invoke(this, m24, new Object[] { paramAdvice })).booleanValue();
    } catch (Error|RuntimeException error) {
      throw null;
    } catch (Throwable throwable) {
      throw new UndeclaredThrowableException(throwable);
    } 
  }
  
  public final void setExposeProxy(boolean paramBoolean) {
    try {
      this.h.invoke(this, m11, new Object[] { Boolean.valueOf(paramBoolean) });
      return;
    } catch (Error|RuntimeException error) {
      throw null;
    } catch (Throwable throwable) {
      throw new UndeclaredThrowableException(throwable);
    } 
  }
  
  public final String hollo() {
    try {
      return (String)this.h.invoke(this, m3, null);
    } catch (Error|RuntimeException error) {
      throw null;
    } catch (Throwable throwable) {
      throw new UndeclaredThrowableException(throwable);
    } 
  }
  
  public final void setTargetSource(TargetSource paramTargetSource) {
    try {
      this.h.invoke(this, m7, new Object[] { paramTargetSource });
      return;
    } catch (Error|RuntimeException error) {
      throw null;
    } catch (Throwable throwable) {
      throw new UndeclaredThrowableException(throwable);
    } 
  }
  
  public final String toString() {
    try {
      return (String)this.h.invoke(this, m2, null);
    } catch (Error|RuntimeException error) {
      throw null;
    } catch (Throwable throwable) {
      throw new UndeclaredThrowableException(throwable);
    } 
  }
  
  public final Class getTargetClass() {
    try {
      return (Class)this.h.invoke(this, m26, null);
    } catch (Error|RuntimeException error) {
      throw null;
    } catch (Throwable throwable) {
      throw new UndeclaredThrowableException(throwable);
    } 
  }
  
  public final void addAdvisor(int paramInt, Advisor paramAdvisor) throws AopConfigException {
    try {
      this.h.invoke(this, m19, new Object[] { Integer.valueOf(paramInt), paramAdvisor });
      return;
    } catch (Error|RuntimeException error) {
      throw null;
    } catch (Throwable throwable) {
      throw new UndeclaredThrowableException(throwable);
    } 
  }
  
  public final Class getDecoratedClass() {
    try {
      return (Class)this.h.invoke(this, m27, null);
    } catch (Error|RuntimeException error) {
      throw null;
    } catch (Throwable throwable) {
      throw new UndeclaredThrowableException(throwable);
    } 
  }
  
  public final boolean removeAdvisor(Advisor paramAdvisor) {
    try {
      return ((Boolean)this.h.invoke(this, m22, new Object[] { paramAdvisor })).booleanValue();
    } catch (Error|RuntimeException error) {
      throw null;
    } catch (Throwable throwable) {
      throw new UndeclaredThrowableException(throwable);
    } 
  }
  
  public final int indexOf(Advice paramAdvice) {
    try {
      return ((Integer)this.h.invoke(this, m5, new Object[] { paramAdvice })).intValue();
    } catch (Error|RuntimeException error) {
      throw null;
    } catch (Throwable throwable) {
      throw new UndeclaredThrowableException(throwable);
    } 
  }
  
  public final boolean isFrozen() {
    try {
      return ((Boolean)this.h.invoke(this, m6, null)).booleanValue();
    } catch (Error|RuntimeException error) {
      throw null;
    } catch (Throwable throwable) {
      throw new UndeclaredThrowableException(throwable);
    } 
  }
  
  public final boolean replaceAdvisor(Advisor paramAdvisor1, Advisor paramAdvisor2) throws AopConfigException {
    try {
      return ((Boolean)this.h.invoke(this, m23, new Object[] { paramAdvisor1, paramAdvisor2 })).booleanValue();
    } catch (Error|RuntimeException error) {
      throw null;
    } catch (Throwable throwable) {
      throw new UndeclaredThrowableException(throwable);
    } 
  }
  
  public final void setPreFiltered(boolean paramBoolean) {
    try {
      this.h.invoke(this, m10, new Object[] { Boolean.valueOf(paramBoolean) });
      return;
    } catch (Error|RuntimeException error) {
      throw null;
    } catch (Throwable throwable) {
      throw new UndeclaredThrowableException(throwable);
    } 
  }
  
  public final String toProxyConfigString() {
    try {
      return (String)this.h.invoke(this, m25, null);
    } catch (Error|RuntimeException error) {
      throw null;
    } catch (Throwable throwable) {
      throw new UndeclaredThrowableException(throwable);
    } 
  }
  
  public final Advisor[] getAdvisors() {
    try {
      return (Advisor[])this.h.invoke(this, m13, null);
    } catch (Error|RuntimeException error) {
      throw null;
    } catch (Throwable throwable) {
      throw new UndeclaredThrowableException(throwable);
    } 
  }
  
  public final boolean isPreFiltered() {
    try {
      return ((Boolean)this.h.invoke(this, m16, null)).booleanValue();
    } catch (Error|RuntimeException error) {
      throw null;
    } catch (Throwable throwable) {
      throw new UndeclaredThrowableException(throwable);
    } 
  }
  
  static {
    try {
      m1 = Class.forName("java.lang.Object").getMethod("equals", new Class[] { Class.forName("java.lang.Object") });
      m12 = Class.forName("org.springframework.aop.framework.Advised").getMethod("isExposeProxy", new Class[0]);
      m20 = Class.forName("org.springframework.aop.framework.Advised").getMethod("addAdvisor", new Class[] { Class.forName("org.springframework.aop.Advisor") });
      m9 = Class.forName("org.springframework.aop.framework.Advised").getMethod("isProxyTargetClass", new Class[0]);
      m21 = Class.forName("org.springframework.aop.framework.Advised").getMethod("removeAdvisor", new Class[] { int.class });
      m17 = Class.forName("org.springframework.aop.framework.Advised").getMethod("getProxiedInterfaces", new Class[0]);
      m4 = Class.forName("org.springframework.aop.framework.Advised").getMethod("indexOf", new Class[] { Class.forName("org.springframework.aop.Advisor") });
      m8 = Class.forName("org.springframework.aop.framework.Advised").getMethod("getTargetSource", new Class[0]);
      m14 = Class.forName("org.springframework.aop.framework.Advised").getMethod("addAdvice", new Class[] { int.class, Class.forName("org.aopalliance.aop.Advice") });
      m15 = Class.forName("org.springframework.aop.framework.Advised").getMethod("addAdvice", new Class[] { Class.forName("org.aopalliance.aop.Advice") });
      m0 = Class.forName("java.lang.Object").getMethod("hashCode", new Class[0]);
      m18 = Class.forName("org.springframework.aop.framework.Advised").getMethod("isInterfaceProxied", new Class[] { Class.forName("java.lang.Class") });
      m24 = Class.forName("org.springframework.aop.framework.Advised").getMethod("removeAdvice", new Class[] { Class.forName("org.aopalliance.aop.Advice") });
      m11 = Class.forName("org.springframework.aop.framework.Advised").getMethod("setExposeProxy", new Class[] { boolean.class });
      m3 = Class.forName("io.github.dunwu.spring.core.aop.example.IOCService").getMethod("hollo", new Class[0]);
      m7 = Class.forName("org.springframework.aop.framework.Advised").getMethod("setTargetSource", new Class[] { Class.forName("org.springframework.aop.TargetSource") });
      m2 = Class.forName("java.lang.Object").getMethod("toString", new Class[0]);
      m26 = Class.forName("org.springframework.aop.framework.Advised").getMethod("getTargetClass", new Class[0]);
      m19 = Class.forName("org.springframework.aop.framework.Advised").getMethod("addAdvisor", new Class[] { int.class, Class.forName("org.springframework.aop.Advisor") });
      m27 = Class.forName("org.springframework.core.DecoratingProxy").getMethod("getDecoratedClass", new Class[0]);
      m22 = Class.forName("org.springframework.aop.framework.Advised").getMethod("removeAdvisor", new Class[] { Class.forName("org.springframework.aop.Advisor") });
      m5 = Class.forName("org.springframework.aop.framework.Advised").getMethod("indexOf", new Class[] { Class.forName("org.aopalliance.aop.Advice") });
      m6 = Class.forName("org.springframework.aop.framework.Advised").getMethod("isFrozen", new Class[0]);
      m23 = Class.forName("org.springframework.aop.framework.Advised").getMethod("replaceAdvisor", new Class[] { Class.forName("org.springframework.aop.Advisor"), Class.forName("org.springframework.aop.Advisor") });
      m10 = Class.forName("org.springframework.aop.framework.Advised").getMethod("setPreFiltered", new Class[] { boolean.class });
      m25 = Class.forName("org.springframework.aop.framework.Advised").getMethod("toProxyConfigString", new Class[0]);
      m13 = Class.forName("org.springframework.aop.framework.Advised").getMethod("getAdvisors", new Class[0]);
      m16 = Class.forName("org.springframework.aop.framework.Advised").getMethod("isPreFiltered", new Class[0]);
      return;
    } catch (NoSuchMethodException noSuchMethodException) {
      throw new NoSuchMethodError(noSuchMethodException.getMessage());
    } catch (ClassNotFoundException classNotFoundException) {
      throw new NoClassDefFoundError(classNotFoundException.getMessage());
    } 
  }
}

Spring AOP中cglib动态代理生成的代理类:

package io.github.dunwu.spring.core.aop.example;

import java.lang.reflect.Method;
import java.lang.reflect.UndeclaredThrowableException;
import org.aopalliance.aop.Advice;
import org.springframework.aop.Advisor;
import org.springframework.aop.SpringProxy;
import org.springframework.aop.TargetClassAware;
import org.springframework.aop.TargetSource;
import org.springframework.aop.framework.Advised;
import org.springframework.aop.framework.AopConfigException;
import org.springframework.cglib.core.ReflectUtils;
import org.springframework.cglib.core.Signature;
import org.springframework.cglib.proxy.Callback;
import org.springframework.cglib.proxy.Dispatcher;
import org.springframework.cglib.proxy.Factory;
import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy;
import org.springframework.cglib.proxy.NoOp;

public class IOCServiceImpl$$EnhancerBySpringCGLIB$$f075506c extends IOCServiceImpl implements SpringProxy, Advised, Factory {
  private boolean CGLIB$BOUND;
  
  public static Object CGLIB$FACTORY_DATA;
  
  private static final ThreadLocal CGLIB$THREAD_CALLBACKS;
  
  private static final Callback[] CGLIB$STATIC_CALLBACKS;
  
  private MethodInterceptor CGLIB$CALLBACK_0;
  
  private MethodInterceptor CGLIB$CALLBACK_1;
  
  private NoOp CGLIB$CALLBACK_2;
  
  private Dispatcher CGLIB$CALLBACK_3;
  
  private Dispatcher CGLIB$CALLBACK_4;
  
  private MethodInterceptor CGLIB$CALLBACK_5;
  
  private MethodInterceptor CGLIB$CALLBACK_6;
  
  private static Object CGLIB$CALLBACK_FILTER;
  
  private static final Method CGLIB$hollo$0$Method;
  
  private static final MethodProxy CGLIB$hollo$0$Proxy;
  
  private static final Object[] CGLIB$emptyArgs;
  
  private static final Method CGLIB$equals$1$Method;
  
  private static final MethodProxy CGLIB$equals$1$Proxy;
  
  private static final Method CGLIB$toString$2$Method;
  
  private static final MethodProxy CGLIB$toString$2$Proxy;
  
  private static final Method CGLIB$hashCode$3$Method;
  
  private static final MethodProxy CGLIB$hashCode$3$Proxy;
  
  private static final Method CGLIB$clone$4$Method;
  
  private static final MethodProxy CGLIB$clone$4$Proxy;
  
  static void CGLIB$STATICHOOK3() {
    CGLIB$THREAD_CALLBACKS = new ThreadLocal();
    CGLIB$emptyArgs = new Object[0];
    Class clazz1 = Class.forName("io.github.dunwu.spring.core.aop.example.IOCServiceImpl$$EnhancerBySpringCGLIB$$f075506c");
    Class clazz2;
    CGLIB$equals$1$Method = ReflectUtils.findMethods(new String[] { "equals", "(Ljava/lang/Object;)Z", "toString", "()Ljava/lang/String;", "hashCode", "()I", "clone", "()Ljava/lang/Object;" }, (clazz2 = Class.forName("java.lang.Object")).getDeclaredMethods())[0];
    CGLIB$equals$1$Proxy = MethodProxy.create(clazz2, clazz1, "(Ljava/lang/Object;)Z", "equals", "CGLIB$equals$1");
    CGLIB$toString$2$Method = ReflectUtils.findMethods(new String[] { "equals", "(Ljava/lang/Object;)Z", "toString", "()Ljava/lang/String;", "hashCode", "()I", "clone", "()Ljava/lang/Object;" }, (clazz2 = Class.forName("java.lang.Object")).getDeclaredMethods())[1];
    CGLIB$toString$2$Proxy = MethodProxy.create(clazz2, clazz1, "()Ljava/lang/String;", "toString", "CGLIB$toString$2");
    CGLIB$hashCode$3$Method = ReflectUtils.findMethods(new String[] { "equals", "(Ljava/lang/Object;)Z", "toString", "()Ljava/lang/String;", "hashCode", "()I", "clone", "()Ljava/lang/Object;" }, (clazz2 = Class.forName("java.lang.Object")).getDeclaredMethods())[2];
    CGLIB$hashCode$3$Proxy = MethodProxy.create(clazz2, clazz1, "()I", "hashCode", "CGLIB$hashCode$3");
    CGLIB$clone$4$Method = ReflectUtils.findMethods(new String[] { "equals", "(Ljava/lang/Object;)Z", "toString", "()Ljava/lang/String;", "hashCode", "()I", "clone", "()Ljava/lang/Object;" }, (clazz2 = Class.forName("java.lang.Object")).getDeclaredMethods())[3];
    CGLIB$clone$4$Proxy = MethodProxy.create(clazz2, clazz1, "()Ljava/lang/Object;", "clone", "CGLIB$clone$4");
    ReflectUtils.findMethods(new String[] { "equals", "(Ljava/lang/Object;)Z", "toString", "()Ljava/lang/String;", "hashCode", "()I", "clone", "()Ljava/lang/Object;" }, (clazz2 = Class.forName("java.lang.Object")).getDeclaredMethods());
    CGLIB$hollo$0$Method = ReflectUtils.findMethods(new String[] { "hollo", "()Ljava/lang/String;" }, (clazz2 = Class.forName("io.github.dunwu.spring.core.aop.example.IOCServiceImpl")).getDeclaredMethods())[0];
    CGLIB$hollo$0$Proxy = MethodProxy.create(clazz2, clazz1, "()Ljava/lang/String;", "hollo", "CGLIB$hollo$0");
    ReflectUtils.findMethods(new String[] { "hollo", "()Ljava/lang/String;" }, (clazz2 = Class.forName("io.github.dunwu.spring.core.aop.example.IOCServiceImpl")).getDeclaredMethods());
  }
  
  final String CGLIB$hollo$0() {
    return super.hollo();
  }
  
  public final String hollo() {
    try {
      if (this.CGLIB$CALLBACK_0 == null)
        CGLIB$BIND_CALLBACKS(this); 
      return (this.CGLIB$CALLBACK_0 != null) ? (String)this.CGLIB$CALLBACK_0.intercept(this, CGLIB$hollo$0$Method, CGLIB$emptyArgs, CGLIB$hollo$0$Proxy) : super.hollo();
    } catch (RuntimeException|Error runtimeException) {
      throw null;
    } catch (Throwable throwable) {
      throw new UndeclaredThrowableException(null);
    } 
  }
  
  final boolean CGLIB$equals$1(Object paramObject) {
    return super.equals(paramObject);
  }
  
  public final boolean equals(Object paramObject) {
    try {
      if (this.CGLIB$CALLBACK_5 == null)
        CGLIB$BIND_CALLBACKS(this); 
      if (this.CGLIB$CALLBACK_5 != null) {
        this.CGLIB$CALLBACK_5.intercept(this, CGLIB$equals$1$Method, new Object[] { paramObject }, CGLIB$equals$1$Proxy);
        return (this.CGLIB$CALLBACK_5.intercept(this, CGLIB$equals$1$Method, new Object[] { paramObject }, CGLIB$equals$1$Proxy) == null) ? false : ((Boolean)this.CGLIB$CALLBACK_5.intercept(this, CGLIB$equals$1$Method, new Object[] { paramObject }, CGLIB$equals$1$Proxy)).booleanValue();
      } 
      return super.equals(paramObject);
    } catch (RuntimeException|Error runtimeException) {
      throw null;
    } catch (Throwable throwable) {
      throw new UndeclaredThrowableException(null);
    } 
  }
  
  final String CGLIB$toString$2() {
    return super.toString();
  }
  
  public final String toString() {
    try {
      if (this.CGLIB$CALLBACK_0 == null)
        CGLIB$BIND_CALLBACKS(this); 
      return (this.CGLIB$CALLBACK_0 != null) ? (String)this.CGLIB$CALLBACK_0.intercept(this, CGLIB$toString$2$Method, CGLIB$emptyArgs, CGLIB$toString$2$Proxy) : super.toString();
    } catch (RuntimeException|Error runtimeException) {
      throw null;
    } catch (Throwable throwable) {
      throw new UndeclaredThrowableException(null);
    } 
  }
  
  final int CGLIB$hashCode$3() {
    return super.hashCode();
  }
  
  public final int hashCode() {
    try {
      if (this.CGLIB$CALLBACK_6 == null)
        CGLIB$BIND_CALLBACKS(this); 
      if (this.CGLIB$CALLBACK_6 != null) {
        this.CGLIB$CALLBACK_6.intercept(this, CGLIB$hashCode$3$Method, CGLIB$emptyArgs, CGLIB$hashCode$3$Proxy);
        return (this.CGLIB$CALLBACK_6.intercept(this, CGLIB$hashCode$3$Method, CGLIB$emptyArgs, CGLIB$hashCode$3$Proxy) == null) ? 0 : ((Number)this.CGLIB$CALLBACK_6.intercept(this, CGLIB$hashCode$3$Method, CGLIB$emptyArgs, CGLIB$hashCode$3$Proxy)).intValue();
      } 
      return super.hashCode();
    } catch (RuntimeException|Error runtimeException) {
      throw null;
    } catch (Throwable throwable) {
      throw new UndeclaredThrowableException(null);
    } 
  }
  
  final Object CGLIB$clone$4() throws CloneNotSupportedException {
    return super.clone();
  }
  
  protected final Object clone() throws CloneNotSupportedException {
    try {
      if (this.CGLIB$CALLBACK_0 == null)
        CGLIB$BIND_CALLBACKS(this); 
      return (this.CGLIB$CALLBACK_0 != null) ? this.CGLIB$CALLBACK_0.intercept(this, CGLIB$clone$4$Method, CGLIB$emptyArgs, CGLIB$clone$4$Proxy) : super.clone();
    } catch (RuntimeException|Error|CloneNotSupportedException runtimeException) {
      throw null;
    } catch (Throwable throwable) {
      throw new UndeclaredThrowableException(null);
    } 
  }
  
  public static MethodProxy CGLIB$findMethodProxy(Signature paramSignature) {
    // Byte code:
    //   0: aload_0
    //   1: invokevirtual toString : ()Ljava/lang/String;
    //   4: dup
    //   5: invokevirtual hashCode : ()I
    //   8: lookupswitch default -> 120, -508378822 -> 60, -272293293 -> 72, 1826985398 -> 84, 1913648695 -> 96, 1984935277 -> 108
    //   60: ldc 'clone()Ljava/lang/Object;'
    //   62: invokevirtual equals : (Ljava/lang/Object;)Z
    //   65: ifeq -> 121
    //   68: getstatic io/github/dunwu/spring/core/aop/example/IOCServiceImpl$$EnhancerBySpringCGLIB$$f075506c.CGLIB$clone$4$Proxy : Lorg/springframework/cglib/proxy/MethodProxy;
    //   71: areturn
    //   72: ldc 'hollo()Ljava/lang/String;'
    //   74: invokevirtual equals : (Ljava/lang/Object;)Z
    //   77: ifeq -> 121
    //   80: getstatic io/github/dunwu/spring/core/aop/example/IOCServiceImpl$$EnhancerBySpringCGLIB$$f075506c.CGLIB$hollo$0$Proxy : Lorg/springframework/cglib/proxy/MethodProxy;
    //   83: areturn
    //   84: ldc 'equals(Ljava/lang/Object;)Z'
    //   86: invokevirtual equals : (Ljava/lang/Object;)Z
    //   89: ifeq -> 121
    //   92: getstatic io/github/dunwu/spring/core/aop/example/IOCServiceImpl$$EnhancerBySpringCGLIB$$f075506c.CGLIB$equals$1$Proxy : Lorg/springframework/cglib/proxy/MethodProxy;
    //   95: areturn
    //   96: ldc 'toString()Ljava/lang/String;'
    //   98: invokevirtual equals : (Ljava/lang/Object;)Z
    //   101: ifeq -> 121
    //   104: getstatic io/github/dunwu/spring/core/aop/example/IOCServiceImpl$$EnhancerBySpringCGLIB$$f075506c.CGLIB$toString$2$Proxy : Lorg/springframework/cglib/proxy/MethodProxy;
    //   107: areturn
    //   108: ldc 'hashCode()I'
    //   110: invokevirtual equals : (Ljava/lang/Object;)Z
    //   113: ifeq -> 121
    //   116: getstatic io/github/dunwu/spring/core/aop/example/IOCServiceImpl$$EnhancerBySpringCGLIB$$f075506c.CGLIB$hashCode$3$Proxy : Lorg/springframework/cglib/proxy/MethodProxy;
    //   119: areturn
    //   120: pop
    //   121: aconst_null
    //   122: areturn
  }
  
  public final int indexOf(Advisor paramAdvisor) {
    try {
      if (this.CGLIB$CALLBACK_4 == null)
        CGLIB$BIND_CALLBACKS(this); 
      return ((Advised)this.CGLIB$CALLBACK_4.loadObject()).indexOf(paramAdvisor);
    } catch (RuntimeException|Error runtimeException) {
      throw null;
    } catch (Throwable throwable) {
      throw new UndeclaredThrowableException(null);
    } 
  }
  
  public final int indexOf(Advice paramAdvice) {
    try {
      if (this.CGLIB$CALLBACK_4 == null)
        CGLIB$BIND_CALLBACKS(this); 
      return ((Advised)this.CGLIB$CALLBACK_4.loadObject()).indexOf(paramAdvice);
    } catch (RuntimeException|Error runtimeException) {
      throw null;
    } catch (Throwable throwable) {
      throw new UndeclaredThrowableException(null);
    } 
  }
  
  public final boolean isFrozen() {
    try {
      if (this.CGLIB$CALLBACK_4 == null)
        CGLIB$BIND_CALLBACKS(this); 
      return ((Advised)this.CGLIB$CALLBACK_4.loadObject()).isFrozen();
    } catch (RuntimeException|Error runtimeException) {
      throw null;
    } catch (Throwable throwable) {
      throw new UndeclaredThrowableException(null);
    } 
  }
  
  public final void addAdvice(Advice paramAdvice) throws AopConfigException {
    try {
      if (this.CGLIB$CALLBACK_4 == null)
        CGLIB$BIND_CALLBACKS(this); 
      ((Advised)this.CGLIB$CALLBACK_4.loadObject()).addAdvice(paramAdvice);
      return;
    } catch (RuntimeException|Error|AopConfigException runtimeException) {
      throw null;
    } catch (Throwable throwable) {
      throw new UndeclaredThrowableException(null);
    } 
  }
  
  public final void addAdvice(int paramInt, Advice paramAdvice) throws AopConfigException {
    try {
      if (this.CGLIB$CALLBACK_4 == null)
        CGLIB$BIND_CALLBACKS(this); 
      ((Advised)this.CGLIB$CALLBACK_4.loadObject()).addAdvice(paramInt, paramAdvice);
      return;
    } catch (RuntimeException|Error|AopConfigException runtimeException) {
      throw null;
    } catch (Throwable throwable) {
      throw new UndeclaredThrowableException(null);
    } 
  }
  
  public final boolean isPreFiltered() {
    try {
      if (this.CGLIB$CALLBACK_4 == null)
        CGLIB$BIND_CALLBACKS(this); 
      return ((Advised)this.CGLIB$CALLBACK_4.loadObject()).isPreFiltered();
    } catch (RuntimeException|Error runtimeException) {
      throw null;
    } catch (Throwable throwable) {
      throw new UndeclaredThrowableException(null);
    } 
  }
  
  public final Class[] getProxiedInterfaces() {
    try {
      if (this.CGLIB$CALLBACK_4 == null)
        CGLIB$BIND_CALLBACKS(this); 
      return ((Advised)this.CGLIB$CALLBACK_4.loadObject()).getProxiedInterfaces();
    } catch (RuntimeException|Error runtimeException) {
      throw null;
    } catch (Throwable throwable) {
      throw new UndeclaredThrowableException(null);
    } 
  }
  
  public final boolean isInterfaceProxied(Class paramClass) {
    try {
      if (this.CGLIB$CALLBACK_4 == null)
        CGLIB$BIND_CALLBACKS(this); 
      return ((Advised)this.CGLIB$CALLBACK_4.loadObject()).isInterfaceProxied(paramClass);
    } catch (RuntimeException|Error runtimeException) {
      throw null;
    } catch (Throwable throwable) {
      throw new UndeclaredThrowableException(null);
    } 
  }
  
  public final void addAdvisor(Advisor paramAdvisor) throws AopConfigException {
    try {
      if (this.CGLIB$CALLBACK_4 == null)
        CGLIB$BIND_CALLBACKS(this); 
      ((Advised)this.CGLIB$CALLBACK_4.loadObject()).addAdvisor(paramAdvisor);
      return;
    } catch (RuntimeException|Error|AopConfigException runtimeException) {
      throw null;
    } catch (Throwable throwable) {
      throw new UndeclaredThrowableException(null);
    } 
  }
  
  public final void addAdvisor(int paramInt, Advisor paramAdvisor) throws AopConfigException {
    try {
      if (this.CGLIB$CALLBACK_4 == null)
        CGLIB$BIND_CALLBACKS(this); 
      ((Advised)this.CGLIB$CALLBACK_4.loadObject()).addAdvisor(paramInt, paramAdvisor);
      return;
    } catch (RuntimeException|Error|AopConfigException runtimeException) {
      throw null;
    } catch (Throwable throwable) {
      throw new UndeclaredThrowableException(null);
    } 
  }
  
  public final void removeAdvisor(int paramInt) throws AopConfigException {
    try {
      if (this.CGLIB$CALLBACK_4 == null)
        CGLIB$BIND_CALLBACKS(this); 
      ((Advised)this.CGLIB$CALLBACK_4.loadObject()).removeAdvisor(paramInt);
      return;
    } catch (RuntimeException|Error|AopConfigException runtimeException) {
      throw null;
    } catch (Throwable throwable) {
      throw new UndeclaredThrowableException(null);
    } 
  }
  
  public final boolean removeAdvisor(Advisor paramAdvisor) {
    try {
      if (this.CGLIB$CALLBACK_4 == null)
        CGLIB$BIND_CALLBACKS(this); 
      return ((Advised)this.CGLIB$CALLBACK_4.loadObject()).removeAdvisor(paramAdvisor);
    } catch (RuntimeException|Error runtimeException) {
      throw null;
    } catch (Throwable throwable) {
      throw new UndeclaredThrowableException(null);
    } 
  }
  
  public final boolean replaceAdvisor(Advisor paramAdvisor1, Advisor paramAdvisor2) throws AopConfigException {
    try {
      if (this.CGLIB$CALLBACK_4 == null)
        CGLIB$BIND_CALLBACKS(this); 
      return ((Advised)this.CGLIB$CALLBACK_4.loadObject()).replaceAdvisor(paramAdvisor1, paramAdvisor2);
    } catch (RuntimeException|Error|AopConfigException runtimeException) {
      throw null;
    } catch (Throwable throwable) {
      throw new UndeclaredThrowableException(null);
    } 
  }
  
  public final boolean removeAdvice(Advice paramAdvice) {
    try {
      if (this.CGLIB$CALLBACK_4 == null)
        CGLIB$BIND_CALLBACKS(this); 
      return ((Advised)this.CGLIB$CALLBACK_4.loadObject()).removeAdvice(paramAdvice);
    } catch (RuntimeException|Error runtimeException) {
      throw null;
    } catch (Throwable throwable) {
      throw new UndeclaredThrowableException(null);
    } 
  }
  
  public final String toProxyConfigString() {
    try {
      if (this.CGLIB$CALLBACK_4 == null)
        CGLIB$BIND_CALLBACKS(this); 
      return ((Advised)this.CGLIB$CALLBACK_4.loadObject()).toProxyConfigString();
    } catch (RuntimeException|Error runtimeException) {
      throw null;
    } catch (Throwable throwable) {
      throw new UndeclaredThrowableException(null);
    } 
  }
  
  public final void setTargetSource(TargetSource paramTargetSource) {
    try {
      if (this.CGLIB$CALLBACK_4 == null)
        CGLIB$BIND_CALLBACKS(this); 
      ((Advised)this.CGLIB$CALLBACK_4.loadObject()).setTargetSource(paramTargetSource);
      return;
    } catch (RuntimeException|Error runtimeException) {
      throw null;
    } catch (Throwable throwable) {
      throw new UndeclaredThrowableException(null);
    } 
  }
  
  public final TargetSource getTargetSource() {
    try {
      if (this.CGLIB$CALLBACK_4 == null)
        CGLIB$BIND_CALLBACKS(this); 
      return ((Advised)this.CGLIB$CALLBACK_4.loadObject()).getTargetSource();
    } catch (RuntimeException|Error runtimeException) {
      throw null;
    } catch (Throwable throwable) {
      throw new UndeclaredThrowableException(null);
    } 
  }
  
  public final boolean isProxyTargetClass() {
    try {
      if (this.CGLIB$CALLBACK_4 == null)
        CGLIB$BIND_CALLBACKS(this); 
      return ((Advised)this.CGLIB$CALLBACK_4.loadObject()).isProxyTargetClass();
    } catch (RuntimeException|Error runtimeException) {
      throw null;
    } catch (Throwable throwable) {
      throw new UndeclaredThrowableException(null);
    } 
  }
  
  public final void setPreFiltered(boolean paramBoolean) {
    try {
      if (this.CGLIB$CALLBACK_4 == null)
        CGLIB$BIND_CALLBACKS(this); 
      ((Advised)this.CGLIB$CALLBACK_4.loadObject()).setPreFiltered(paramBoolean);
      return;
    } catch (RuntimeException|Error runtimeException) {
      throw null;
    } catch (Throwable throwable) {
      throw new UndeclaredThrowableException(null);
    } 
  }
  
  public final void setExposeProxy(boolean paramBoolean) {
    try {
      if (this.CGLIB$CALLBACK_4 == null)
        CGLIB$BIND_CALLBACKS(this); 
      ((Advised)this.CGLIB$CALLBACK_4.loadObject()).setExposeProxy(paramBoolean);
      return;
    } catch (RuntimeException|Error runtimeException) {
      throw null;
    } catch (Throwable throwable) {
      throw new UndeclaredThrowableException(null);
    } 
  }
  
  public final boolean isExposeProxy() {
    try {
      if (this.CGLIB$CALLBACK_4 == null)
        CGLIB$BIND_CALLBACKS(this); 
      return ((Advised)this.CGLIB$CALLBACK_4.loadObject()).isExposeProxy();
    } catch (RuntimeException|Error runtimeException) {
      throw null;
    } catch (Throwable throwable) {
      throw new UndeclaredThrowableException(null);
    } 
  }
  
  public final Advisor[] getAdvisors() {
    try {
      if (this.CGLIB$CALLBACK_4 == null)
        CGLIB$BIND_CALLBACKS(this); 
      return ((Advised)this.CGLIB$CALLBACK_4.loadObject()).getAdvisors();
    } catch (RuntimeException|Error runtimeException) {
      throw null;
    } catch (Throwable throwable) {
      throw new UndeclaredThrowableException(null);
    } 
  }
  
  public final Class getTargetClass() {
    try {
      if (this.CGLIB$CALLBACK_4 == null)
        CGLIB$BIND_CALLBACKS(this); 
      return ((TargetClassAware)this.CGLIB$CALLBACK_4.loadObject()).getTargetClass();
    } catch (RuntimeException|Error runtimeException) {
      throw null;
    } catch (Throwable throwable) {
      throw new UndeclaredThrowableException(null);
    } 
  }
  
  public static void CGLIB$SET_THREAD_CALLBACKS(Callback[] paramArrayOfCallback) {
    CGLIB$THREAD_CALLBACKS.set(paramArrayOfCallback);
  }
  
  public static void CGLIB$SET_STATIC_CALLBACKS(Callback[] paramArrayOfCallback) {
    CGLIB$STATIC_CALLBACKS = paramArrayOfCallback;
  }
  
  private static final void CGLIB$BIND_CALLBACKS(Object paramObject) {
    IOCServiceImpl$$EnhancerBySpringCGLIB$$f075506c iOCServiceImpl$$EnhancerBySpringCGLIB$$f075506c = (IOCServiceImpl$$EnhancerBySpringCGLIB$$f075506c)paramObject;
    if (!iOCServiceImpl$$EnhancerBySpringCGLIB$$f075506c.CGLIB$BOUND) {
      iOCServiceImpl$$EnhancerBySpringCGLIB$$f075506c.CGLIB$BOUND = true;
      if (CGLIB$THREAD_CALLBACKS.get() == null) {
        CGLIB$THREAD_CALLBACKS.get();
        if (CGLIB$STATIC_CALLBACKS == null)
          return; 
      } 
      iOCServiceImpl$$EnhancerBySpringCGLIB$$f075506c.CGLIB$CALLBACK_6 = (MethodInterceptor)((Callback[])CGLIB$THREAD_CALLBACKS.get())[6];
      iOCServiceImpl$$EnhancerBySpringCGLIB$$f075506c.CGLIB$CALLBACK_5 = (MethodInterceptor)((Callback[])CGLIB$THREAD_CALLBACKS.get())[5];
      iOCServiceImpl$$EnhancerBySpringCGLIB$$f075506c.CGLIB$CALLBACK_4 = (Dispatcher)((Callback[])CGLIB$THREAD_CALLBACKS.get())[4];
      iOCServiceImpl$$EnhancerBySpringCGLIB$$f075506c.CGLIB$CALLBACK_3 = (Dispatcher)((Callback[])CGLIB$THREAD_CALLBACKS.get())[3];
      iOCServiceImpl$$EnhancerBySpringCGLIB$$f075506c.CGLIB$CALLBACK_2 = (NoOp)((Callback[])CGLIB$THREAD_CALLBACKS.get())[2];
      iOCServiceImpl$$EnhancerBySpringCGLIB$$f075506c.CGLIB$CALLBACK_1 = (MethodInterceptor)((Callback[])CGLIB$THREAD_CALLBACKS.get())[1];
      iOCServiceImpl$$EnhancerBySpringCGLIB$$f075506c.CGLIB$CALLBACK_0 = (MethodInterceptor)((Callback[])CGLIB$THREAD_CALLBACKS.get())[0];
    } 
  }
  
  public Object newInstance(Callback[] paramArrayOfCallback) {
    try {
      CGLIB$SET_THREAD_CALLBACKS(paramArrayOfCallback);
      CGLIB$SET_THREAD_CALLBACKS(null);
      return new IOCServiceImpl$$EnhancerBySpringCGLIB$$f075506c();
    } catch (RuntimeException|Error runtimeException) {
      throw null;
    } catch (Throwable throwable) {
      throw new UndeclaredThrowableException(null);
    } 
  }
  
  public Object newInstance(Callback paramCallback) {
    try {
      throw new IllegalStateException("More than one callback object required");
    } catch (RuntimeException|Error runtimeException) {
      throw null;
    } catch (Throwable throwable) {
      throw new UndeclaredThrowableException(null);
    } 
  }
  
  public Object newInstance(Class[] paramArrayOfClass, Object[] paramArrayOfObject, Callback[] paramArrayOfCallback) {
    // Byte code:
    //   0: aload_3
    //   1: invokestatic CGLIB$SET_THREAD_CALLBACKS : ([Lorg/springframework/cglib/proxy/Callback;)V
    //   4: new io/github/dunwu/spring/core/aop/example/IOCServiceImpl$$EnhancerBySpringCGLIB$$f075506c
    //   7: dup
    //   8: aload_1
    //   9: dup
    //   10: arraylength
    //   11: tableswitch default -> 35, 0 -> 28
    //   28: pop
    //   29: invokespecial <init> : ()V
    //   32: goto -> 50
    //   35: goto -> 38
    //   38: pop
    //   39: new java/lang/IllegalArgumentException
    //   42: dup
    //   43: ldc_w 'Constructor not found'
    //   46: invokespecial <init> : (Ljava/lang/String;)V
    //   49: athrow
    //   50: aconst_null
    //   51: invokestatic CGLIB$SET_THREAD_CALLBACKS : ([Lorg/springframework/cglib/proxy/Callback;)V
    //   54: areturn
    //   55: athrow
    //   56: new java/lang/reflect/UndeclaredThrowableException
    //   59: dup_x1
    //   60: swap
    //   61: invokespecial <init> : (Ljava/lang/Throwable;)V
    //   64: athrow
    // Exception table:
    //   from   to  target  type
    //   0  55  55  java/lang/RuntimeException
    //   0  55  55  java/lang/Error
    //   0  55  56  java/lang/Throwable
  }
  
  public Callback getCallback(int paramInt) {
    try {
      CGLIB$BIND_CALLBACKS(this);
      switch (paramInt) {
        case 0:
        
        case 1:
        
        case 2:
        
        case 3:
        
        case 4:
        
        case 5:
        
        case 6:
        
      } 
      return null;
    } catch (RuntimeException|Error runtimeException) {
      throw null;
    } catch (Throwable throwable) {
      throw new UndeclaredThrowableException(null);
    } 
  }
  
  public void setCallback(int paramInt, Callback paramCallback) {
    try {
      switch (paramInt) {
        case 0:
          this.CGLIB$CALLBACK_0 = (MethodInterceptor)paramCallback;
          break;
        case 1:
          this.CGLIB$CALLBACK_1 = (MethodInterceptor)paramCallback;
          break;
        case 2:
          this.CGLIB$CALLBACK_2 = (NoOp)paramCallback;
          break;
        case 3:
          this.CGLIB$CALLBACK_3 = (Dispatcher)paramCallback;
          break;
        case 4:
          this.CGLIB$CALLBACK_4 = (Dispatcher)paramCallback;
          break;
        case 5:
          this.CGLIB$CALLBACK_5 = (MethodInterceptor)paramCallback;
          break;
        case 6:
          this.CGLIB$CALLBACK_6 = (MethodInterceptor)paramCallback;
          break;
      } 
      return;
    } catch (RuntimeException|Error runtimeException) {
      throw null;
    } catch (Throwable throwable) {
      throw new UndeclaredThrowableException(null);
    } 
  }
  
  public Callback[] getCallbacks() {
    try {
      CGLIB$BIND_CALLBACKS(this);
      return new Callback[] { (Callback)this.CGLIB$CALLBACK_0, (Callback)this.CGLIB$CALLBACK_1, (Callback)this.CGLIB$CALLBACK_2, (Callback)this.CGLIB$CALLBACK_3, (Callback)this.CGLIB$CALLBACK_4, (Callback)this.CGLIB$CALLBACK_5, (Callback)this.CGLIB$CALLBACK_6 };
    } catch (RuntimeException|Error runtimeException) {
      throw null;
    } catch (Throwable throwable) {
      throw new UndeclaredThrowableException(null);
    } 
  }
  
  public void setCallbacks(Callback[] paramArrayOfCallback) {
    try {
      this.CGLIB$CALLBACK_0 = (MethodInterceptor)paramArrayOfCallback[0];
      this.CGLIB$CALLBACK_1 = (MethodInterceptor)paramArrayOfCallback[1];
      this.CGLIB$CALLBACK_2 = (NoOp)paramArrayOfCallback[2];
      this.CGLIB$CALLBACK_3 = (Dispatcher)paramArrayOfCallback[3];
      this.CGLIB$CALLBACK_4 = (Dispatcher)paramArrayOfCallback[4];
      this.CGLIB$CALLBACK_5 = (MethodInterceptor)paramArrayOfCallback[5];
      this.CGLIB$CALLBACK_6 = (MethodInterceptor)paramArrayOfCallback[6];
      return;
    } catch (RuntimeException|Error runtimeException) {
      throw null;
    } catch (Throwable throwable) {
      throw new UndeclaredThrowableException(null);
    } 
  }
  
  static {
    CGLIB$STATICHOOK4();
    CGLIB$STATICHOOK3();
  }
  
  static void CGLIB$STATICHOOK4() {
    try {
      return;
    } catch (RuntimeException|Error runtimeException) {
      throw null;
    } catch (Throwable throwable) {
      throw new UndeclaredThrowableException(null);
    } 
  }
}

相关文章

网友评论

      本文标题:初识AOP:Spring AOP框架

      本文链接:https://www.haomeiwen.com/subject/tshuphtx.html