美文网首页
spring aop 源码解析

spring aop 源码解析

作者: futureluck | 来源:发表于2019-02-21 10:26 被阅读0次

aop面向切面编程,想必都非常熟悉了。本文采用明星和经纪人举例:经纪人是代理对象,明星是被代理对象。 本文根据下面的流程实例,讲解spring aop的源码。

带着这些问题去了解AOP

1.CGLIB代理和JDK代理,spring怎么判断选择?
2.Bean单例被代理情况下,只有一个公有的无参的构造函数。
CGLib方式下,构造函数会调用几次?jdk代理情况下,构造函数会调用几次?
3.CGlib代理,方法调用采用fastClass执行的原理是什么?
4.增强怎么和代理类的执行绑定在一起,比如你写了5个切面方法,执行方法的时候怎么联系到一起?

基本概念

连接点(Joinpoint):连接点就是方法的调用前,调用后,异常抛出后等位置的定义
切点(Pointcut):就是筛选出连接点的条件,比如一个类的3个方法,只对String返回的方法做增强。
增强(Advice):就是在“连接点”做的功能,比如打印日志,提交事务。
引介(Introduction):本来这个类没有功能,通过代理继承其他接口,动态实现该功能。
织入(Weaving):就是把增强植入到特地点去执行。比如植入到方法执行前,感觉这个就是代理方法生成的时候,操作的事情。
切面(Aspect):切面是由切点和增强(引介)组成,就是定义了,在哪些代码地方(连接点)里做增强(advice)的事情。

重要的类和接口介绍

Advise:增强对象,代理对象为被代理对象多加的技能,如明星在拍戏之前,经纪人为明星谈合同、签合约。
Advisor:Base interface holding AOP advice。
Advised:拥有获取ProxyConfig、获取拦截器功能、获取、添加advise增强。
ProxyFactory:代理对象的创建工厂类,通过创建AopProxyFactory创建AopProxy代理对象。定义了获取和配置AOPProxy对象的行为,而又把具体的功能下放到AopProxyFactory去。
ProxyConfig:封装创建代理对象配置,重要属性介绍如下

proxyTargetClass属性:是否直接代理目标类,否的话用接口代理,比如jdk代理,是的话用CGLIB代理目标类。
optimize属性:是否执行某些优化。
opaque属性:是否能转换成Advised接口, Return whether proxies created by this configuration should be prevented from being cast to Advised。
frozen属性:当前代理配置是否被冻结,如果被冻结,配置将不能被修改。
exposeProxy属性:是否暴露代理,也就是是否把当前代理对象绑定到AopContext的ThreadLocal属性currentProxy上去,常用于代理类里面的代理方法需要调用同类里面另外一个代理方法的场景。方法内执行的时候可以通过上下文再次获取到当前的代理对象。比如A B都是被代理的方法,A中执行B方法,则只会切一次。通过上下文获取代理对象,再执行B方法,两个方法都可以被切。

AopProxy:aop代理对象,他的作用就是获取到实际的被代理对象。(经纪人对象)
AopProxyFactory:代理对象工厂,这个就是代理对象工厂,获取代理对象。(经纪人对象工厂)
DefaultAopProxyFactory:默认代理对象工厂实现
JdkDynamicAopProxy:jdk代理对象
ObjenesisCglibAopProxy:CGLIB代理对象

创建过程

  • spring会根据配置创建bean,判断需要代理情况下,并创建代理对象
// AbstractAutowireCapableBeanFactory 创建bean
protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args)           throws BeanCreationException {

        // Instantiate the bean. 
        // 实例化bean
        BeanWrapper instanceWrapper = null;
        if (mbd.isSingleton()) {
            instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
        }
        if (instanceWrapper == null) {
            instanceWrapper = createBeanInstance(beanName, mbd, args);
        }
        final Object bean = instanceWrapper.getWrappedInstance();
    
        // Initialize the bean instance.
        // 实例化bean
        Object exposedObject = bean;
        try {
            // Populate the bean instance in the given BeanWrapper with the property values from the bean definition. 即填充Bean的属性
            // 填充bean的属性,mbd:the bean definition for the bean
            populateBean(beanName, mbd, instanceWrapper);
            // 这里实例化,如果是代理类的,这里返回的的是代理类的实例
            // 疑问1:populateBean已经设置好属性了,下一步怎么把已经设置好的属性transfer给代理类
            exposedObject = initializeBean(beanName, exposedObject, mbd);
        }
        catch (Throwable ex) {
            if (ex instanceof BeanCreationException && beanName.equals(((BeanCreationException) ex).getBeanName())) {
                throw (BeanCreationException) ex;
            }
            else {
                throw new BeanCreationException(
                        mbd.getResourceDescription(), beanName, "Initialization of bean failed", ex);
            }
        }

               if (earlySingletonExposure) {
                         // getSingleton方法就会把代理类注册到容器
               Object earlySingletonReference = getSingleton(beanName, false);
                }

        // InitializingBean与DisposableBean
                // DisposableBean销毁需要调用destroy方法
        registerDisposableBeanIfNecessary(beanName, bean, mbd);
    
        return exposedObject;
    }
  • 创建bean之后,AbstractAutowireCapableBeanFactory获取所有的BeanPostProcessor循环遍历处理。进而调用到AbstractAutoProxyCreator.wrapIfNecessary方法,去创建代理对象。
    // ProxyFactory的配置透传给AopProxyFactory
    // AbstractAutoProxyCreator每次创建代理,都会创建一个工程
       // 解释下这个参数specificInterceptors
      // 参考AbstractAutoProxyCreator类getAdvicesAndAdvisorsForBean,获取增强for bean
protected Object createProxy(Class<?> beanClass, @Nullable String beanName,
            @Nullable Object[] specificInterceptors, TargetSource targetSource) {

        if (this.beanFactory instanceof ConfigurableListableBeanFactory) {
            AutoProxyUtils.exposeTargetClass((ConfigurableListableBeanFactory) this.beanFactory, beanName, beanClass);
        }

        // 创建工厂的同事,创建advised config
        ProxyFactory proxyFactory = new ProxyFactory();
        // 当前的AbstractAutoProxyCreator的ProxyConfig配置,透传给ProxyFactory
        // 后续流转中ProxyFactory再把这个配置透传AopProxyFactory
        proxyFactory.copyFrom(this);

        if (!proxyFactory.isProxyTargetClass()) {
            if (shouldProxyTargetClass(beanClass, beanName)) {
                proxyFactory.setProxyTargetClass(true);
            }
            else {
                evaluateProxyInterfaces(beanClass, proxyFactory);
            }
        }

        // 注意这句话就是找到所有的增强,并加入到代理类
        Advisor[] advisors = buildAdvisors(beanName, specificInterceptors);
        proxyFactory.addAdvisors(advisors);
        proxyFactory.setTargetSource(targetSource);
        customizeProxyFactory(proxyFactory);

        proxyFactory.setFrozen(this.freezeProxy);
        if (advisorsPreFiltered()) {
            proxyFactory.setPreFiltered(true);
        }
                // 真正的创建代理对象
        return proxyFactory.getProxy(getProxyClassLoader());
    }
  • 继续往下看怎么获取增强
// 获取特别的拦截器
// AbstractAdvisorAutoProxyCreator.getAdvicesAndAdvisorsForBean 获取增强
protected Object[] getAdvicesAndAdvisorsForBean(
            Class<?> beanClass, String beanName, @Nullable TargetSource targetSource) {

    List<Advisor> advisors = findEligibleAdvisors(beanClass, beanName);
    if (advisors.isEmpty()) {
            return DO_NOT_PROXY;
    }
    return advisors.toArray();
}
    
    
// 通过bean找到增强
protected List<Advisor> findEligibleAdvisors(Class<?> beanClass, String beanName) {
    // candidate 报考者、参加者
    // 找到所有的增强
    // 这个不难,beanFactory.getBean(name, Advisor.class),就是通过beanFactory拿到      
    List<Advisor> candidateAdvisors = findCandidateAdvisors();
    // 根据beanClass和beanName去过滤
    // execution 去过滤
    List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);
    // 留个空实现,给后面的扩展
    extendAdvisors(eligibleAdvisors);
    if (!eligibleAdvisors.isEmpty()) {
        // 排序
        eligibleAdvisors = sortAdvisors(eligibleAdvisors);
    }
    // 返回
    return eligibleAdvisors;
}


// AbstractAutoProxyCreator.buildAdvisors做了两件事情 
// 1.把公共的增强加进去  
//2.加入特别的拦截器,也就是独有的
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));
                }
            }
        }
        
        Advisor[] advisors = new Advisor[allInterceptors.size()];
        for (int i = 0; i < allInterceptors.size(); i++) {
            advisors[i] = this.advisorAdapterRegistry.wrap(allInterceptors.get(i));
        }
        return advisors;
    }

  • ProxyFactory通过AopProxy 创建代理对象,以下拿CglibAopProxy作为示例
// CglibAopProxy.getProxy()创建代理的示例
// createProxyClassAndInstance(enhancer, callbacks);
// 有意思的是ObjenesisCglibAopProxy这个类,看类的描述:即创建代理实例,不调用类的构造函数。
// Objenesis-based extension of {@link CglibAopProxy} to create proxy instances without invoking the constructor of the class.

// enhancer的关键步骤,1设置父类 2设置callback  
public Object getProxy(Class clazz) {
    //设置父类
    enhancer.setSuperclass(clazz);
    enhancer.setCallback(this);    
    //不调用构造函数,去生成对象
    SpringObjenesis objenesis = new SpringObjenesis();
    Object proxyInstance = objenesis.newInstance(clazz, enhancer.getUseCache());
    if (proxyInstance != null) {
        return proxyInstance;
    }
    //通过字节码技术动态创建子类实例
    return enhancer.create();
}


private Callback[] getCallbacks(Class<?> rootClass) throws Exception {
    // Parameters used for optimization choices...
    boolean exposeProxy = this.advised.isExposeProxy();
    boolean isFrozen = this.advised.isFrozen();
    boolean isStatic = this.advised.getTargetSource().isStatic();

    // Choose an "aop" interceptor (used for AOP calls).
    Callback aopInterceptor = new DynamicAdvisedInterceptor(this.advised);

    // Choose a "straight to target" interceptor. (used for calls that are
    // unadvised but can return this). May be required to expose the proxy.
    Callback targetInterceptor;
    if (exposeProxy) {
        targetInterceptor = (isStatic ?
                new StaticUnadvisedExposedInterceptor(this.advised.getTargetSource().getTarget()) :
                new DynamicUnadvisedExposedInterceptor(this.advised.getTargetSource()));
    }
    else {
        targetInterceptor = (isStatic ?
                new StaticUnadvisedInterceptor(this.advised.getTargetSource().getTarget()) :
                new DynamicUnadvisedInterceptor(this.advised.getTargetSource()));
    }

    // Choose a "direct to target" dispatcher (used for
    // unadvised calls to static targets that cannot return this).
    Callback targetDispatcher = (isStatic ?
            new StaticDispatcher(this.advised.getTargetSource().getTarget()) : new SerializableNoOp());
    
    // 获取callback的关键代码,都是固定的几个interceptor
    // 假如写了三个切面,我们是通过DynamicAdvisedInterceptor对象去查找执行链路,并不是在这里加了三个interceptor
    Callback[] mainCallbacks = new Callback[] {
            aopInterceptor,  // for normal advice
            targetInterceptor,  // invoke target without considering advice, if optimized
            new SerializableNoOp(),  // no override for methods mapped to this
            targetDispatcher, this.advisedDispatcher,
            new EqualsInterceptor(this.advised),
            new HashCodeInterceptor(this.advised)
    };

    Callback[] callbacks;

    // If the target is a static one and the advice chain is frozen,
    // then we can make some optimizations by sending the AOP calls
    // direct to the target using the fixed chain for that method.
    if (isStatic && isFrozen) {
        Method[] methods = rootClass.getMethods();
        Callback[] fixedCallbacks = new Callback[methods.length];
        this.fixedInterceptorMap = new HashMap<>(methods.length);

        // TODO: small memory optimization here (can skip creation for methods with no advice)
        for (int x = 0; x < methods.length; x++) {
            List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(methods[x], rootClass);
            fixedCallbacks[x] = new FixedChainStaticTargetInterceptor(
                    chain, this.advised.getTargetSource().getTarget(), this.advised.getTargetClass());
            this.fixedInterceptorMap.put(methods[x].toString(), x);
        }

        // Now copy both the callbacks from mainCallbacks
        // and fixedCallbacks into the callbacks array.
        callbacks = new Callback[mainCallbacks.length + fixedCallbacks.length];
        System.arraycopy(mainCallbacks, 0, callbacks, 0, mainCallbacks.length);
        System.arraycopy(fixedCallbacks, 0, callbacks, mainCallbacks.length, fixedCallbacks.length);
        this.fixedInterceptorOffset = mainCallbacks.length;
    }
    else {
        callbacks = mainCallbacks;
    }
    return callbacks;
}

  • 特别说明不调用构造函数创建代理对象
/**
 * 写个示例类
 * 照理说,这个类每次被执行一次就会被调用一次i++
 * 但是用ObjenesisCglibAopProxy,无需调用构造函数。
 * spring是不耦合业务的,设想有个什么业务做在构造函数里而类是单例,你用cglib生成代理类,实例化的时候,不是把构造函数多执行一次
 * 这就违背了spring设计的初衷了。原理参考newInstance();方法
 *
 */
@Service
@Slf4j
public class MyUserService {
    public static int i = 0;


    public MyUserService() {
        synchronized (MyUserService.class) {
            i++;
            System.out.println("sync i:" + i);
        }
    }

    public static void newInstance() {
        try {
            ReflectionFactory reflectionFactory = ReflectionFactory.getReflectionFactory();
            Constructor<?> constructor = reflectionFactory.newConstructorForSerialization(MyUserService.class, Object.class.getDeclaredConstructor());
            constructor.setAccessible(true);
            Object instance = constructor.newInstance();
        } catch (Exception e) {
            e.printStackTrace();
        }

    }
}
  • 向spring容器注册代理实例(经纪人对象),其holding了被代理的对象,即target对象(明星对象)
// DefaultSingletonBeanRegistry会把代理的类注册到spring 容器
// 此类是通用的,不管是不是代理对象,只要符合单例都会执行下面的逻辑
@Nullable
protected Object getSingleton(String beanName, boolean allowEarlyReference) {
    Object singletonObject = this.singletonObjects.get(beanName);
    // 容器不存在,则向容器中添加
    if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
        synchronized (this.singletonObjects) {
            singletonObject = this.earlySingletonObjects.get(beanName);
            if (singletonObject == null && allowEarlyReference) {
                ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
                if (singletonFactory != null) {
                    singletonObject = singletonFactory.getObject();
                    this.earlySingletonObjects.put(beanName, singletonObject);
                    this.singletonFactories.remove(beanName);
                }
            }
        }
    }
    // 存在直接返回
    return singletonObject;
}

调用过程

  • 实际调用代理对象的方法,通过spring ioc获取到代理对象。

下面用一个示例来说明,调用userService.queryByLoginName()方法,用反编译可以看到调用链

  // 对父类方法的重新
 // 1. 先获取回调对象(若无,尝试设置)
// 2.若有,则调用回调对象的intercept方法。
// 3.若无,则调用父类对象的对应方法。
// 在回调类中的代理方法具体调用,可查看MethodProxy 和 Method 的invoke 或 invokeSuper方法

  public final String queryByLoginName()
  {
    try
    {
     // 先设置回调拦截
      MethodInterceptor tmp4_1 = this.CGLIB$CALLBACK_0;
      if (tmp4_1 == null)
      {
        tmp4_1;
        CGLIB$BIND_CALLBACKS(this);
      }
      MethodInterceptor tmp17_14 = this.CGLIB$CALLBACK_0;
      // 有拦截,则直接拦截处理
      if (tmp17_14 != null) {
        return (String)tmp17_14.intercept(this, CGLIB$queryByLoginName$0$Method, CGLIB$emptyArgs, CGLIB$queryByLoginName$0$Proxy);
      }
      //没有拦截,则直接invoke父类
      return super.queryByLoginName();
  }
  • 看上面方法,最终还是调用MethodInterceptor类intercept方法
  // spring 去做拦截:CglibAopProxy.DynamicAdvisedInterceptor.intercept
  public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
            Object oldProxy = null;
            boolean setProxyContext = false;
            Object target = null;
            TargetSource targetSource = this.advised.getTargetSource();
            try {
            
                // 是否暴露代理对象,其他地方,再次用的话可能用的上。比如事务的隔离级别
                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);
                // 这个就是调用链,假如没有任何拦截,肯定是empty
                // 这你写了几个aspect,就会有几个调用链
                List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
                Object retVal;
                // Check whether we only have one InvokerInterceptor: that is,
                // no real advice, but just reflective invocation of the target.
                // 判断有没有调用链,如果没有调用链,直接invoke就行了
                
                if (chain.isEmpty() && Modifier.isPublic(method.getModifiers())) {
                    // 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);
                    // 直接调用源目标的方法就行,因为没有任何代理并且方法也是private
                    retVal = methodProxy.invoke(target, argsToUse);
                }
                else {
                    // We need to create a method invocation...
                    // 生成Cglib method invocation,即代理类的方法执行器
                    // proceed 前进执行
                    retVal = new CglibMethodInvocation(proxy, target, method, args, targetClass, chain, methodProxy).proceed();
                }
                retVal = processReturnType(proxy, target, method, retVal);
                return retVal;
            }
            finally {
                if (target != null && !targetSource.isStatic()) {
                    // 精妙之处,如果源目标对象不为空,并且不是静态的。则要移除。简单说,不是单例的,就要移除。
                    // SingletonTargetSource
                    // PrototypeTargetSource
                    targetSource.releaseTarget(target);
                }
                if (setProxyContext) {
                    // Restore old proxy.
                    AopContext.setCurrentProxy(oldProxy);
                }
            }
        }
  • 下面追踪怎么获取拦截的增强
// DefaultAdvisorChainFactory.getInterceptorsAndDynamicInterceptionAdvice 获取拦截的增强
public List<Object> getInterceptorsAndDynamicInterceptionAdvice(Method method, @Nullable Class<?> targetClass) {
    MethodCacheKey cacheKey = new MethodCacheKey(method);
    List<Object> cached = this.methodCache.get(cacheKey);
    if (cached == null) {
        cached = this.advisorChainFactory.getInterceptorsAndDynamicInterceptionAdvice(
                this, method, targetClass);
        this.methodCache.put(cacheKey, cached);
    }
    return cached;
}


DefaultAdvisorChainFactory.getInterceptorsAndDynamicInterceptionAdvice();

@Override
public List<Object> getInterceptorsAndDynamicInterceptionAdvice(
        Advised config, Method method, @Nullable Class<?> targetClass) {

    // This is somewhat tricky... We have to process introductions first,
    // but we need to preserve order in the ultimate list.
    // 这个就是你写了个几个增强,就有几个方法。比如你写了10个切面,则有10个
    // AdvisedSupport方法获取getAdvisors(),实现的是Advised配置接口类
    List<Object> interceptorList = new ArrayList<Object>(config.getAdvisors().length);
    Class<?> actualClass = (targetClass != null ? targetClass : method.getDeclaringClass());
    boolean hasIntroductions = hasMatchingIntroductions(config, actualClass);
    AdvisorAdapterRegistry registry = GlobalAdvisorAdapterRegistry.getInstance();
         // 注意看config.getAdvisors(),
        // 配置类,我们在创建代理对象的时候,ProxyFactory透传来的
       // 看上面创建代理的过程,你搜索下面的这行代码,就会明白啥意思了。
       // Advisor[] advisors = buildAdvisors(beanName, specificInterceptors)
    for (Advisor advisor : config.getAdvisors()) {
        if (advisor instanceof PointcutAdvisor) {
            // Add it conditionally.
            PointcutAdvisor pointcutAdvisor = (PointcutAdvisor) advisor;
            if (config.isPreFiltered() || pointcutAdvisor.getPointcut().getClassFilter().matches(actualClass)) {
                MethodMatcher mm = pointcutAdvisor.getPointcut().getMethodMatcher();
                if (MethodMatchers.matches(mm, method, actualClass, hasIntroductions)) {
                    MethodInterceptor[] interceptors = registry.getInterceptors(advisor);
                    if (mm.isRuntime()) {
                        // Creating a new object instance in the getInterceptors() method
                        // isn't a problem as we normally cache created chains.
                        for (MethodInterceptor interceptor : interceptors) {
                            interceptorList.add(new InterceptorAndDynamicMethodMatcher(interceptor, mm));
                        }
                    }
                    else {
                        interceptorList.addAll(Arrays.asList(interceptors));
                    }
                }
            }
        }
        else if (advisor instanceof IntroductionAdvisor) {
            IntroductionAdvisor ia = (IntroductionAdvisor) advisor;
            if (config.isPreFiltered() || ia.getClassFilter().matches(actualClass)) {
                Interceptor[] interceptors = registry.getInterceptors(advisor);
                interceptorList.addAll(Arrays.asList(interceptors));
            }
        }
        else {
            Interceptor[] interceptors = registry.getInterceptors(advisor);
            interceptorList.addAll(Arrays.asList(interceptors));
        }
    }

    return interceptorList;
}

相关文章

网友评论

      本文标题:spring aop 源码解析

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