Spring源碼閱讀----Spring AOP使用和源碼解析

概述

Spring經常被人提及的就是IOC和AOP敬察,前邊在介紹IOC的時候艇挨,我們已經提及到了AOP,還記得起來嗎?
在《Spring源碼閱讀----Spring IoC之finishBeanFactoryInitialization(續(xù))很重要的createBean》一文中恤溶,介紹到有些實現了InstantiationAwareBeanPostProcessor接口的AbstractAutoProxyCreator類,其子類AnnotationAwareAutoProxyCreator是個很重要的類帜羊。

啥是AOP

AOP(Aspect Oriented Programming)宏娄,面向切面思想,可以百度一下其概念逮壁。比如日志打印等邊緣需求會散落在多處業(yè)務中孵坚,重復寫冗余代碼會影響項目維護,而AOP就是將這類主業(yè)務以外的代碼提取出來窥淆,使其分離卖宠,然后在這些業(yè)務中尋找切入點,然后將分離的非業(yè)務代碼切入業(yè)務中忧饭。

實踐一下

下面來看一個例子,在原來的SSM demo里改造

  1. 在pom文件中加入依賴包
    <dependency>
      <groupId>org.aspectj</groupId>
      <artifactId>aspectjrt</artifactId>
      <version>1.9.5</version>
    </dependency>

    <dependency>
      <groupId>org.aspectj</groupId>
      <artifactId>aspectjweaver</artifactId>
      <version>1.9.5</version>
    </dependency>
  1. 創(chuàng)建一個切面類AopTest
@Component
@Aspect
public class AopTest {
    
    @Pointcut("execution(* com.zhlab..ssm.demo.web.controller.TestController.*(..))")
    public void pointCut(){}

    @Before("pointCut()")
    public void beforeMethod(JoinPoint joinPoint){
        System.out.println("前置通知before start");
        String methodName = joinPoint.getSignature().getName();
        System.out.println("前置通知before end");
    }

    @After("pointCut()")
    public void afterMethod(JoinPoint joinPoint){
        System.out.println("后置通知after start");
        String methodName = joinPoint.getSignature().getName();
        System.out.println("后置通知after end");
    }

    @Around("pointCut()")
    public Object aroundMethod(ProceedingJoinPoint joinPoint) throws Throwable {
        System.out.println("環(huán)繞通知after start");
        String methodName = joinPoint.getSignature().getName();
        Object result = joinPoint.proceed();//執(zhí)行業(yè)務具體業(yè)務邏輯
        System.out.println("環(huán)繞通知after end");
        return result;
    }
}

類上加上兩個注解@Component扛伍、@Aspect
注解@Aspect表示當前類是一個切面,添加@Component注解表示當前類需要初始化一個bean到Spring容器中,這個類里只使用了@Before词裤、@After刺洒、@Around三個方法注解,總的有以下幾個注解:

  • @Before注解修飾方法表示當前方法會在連接點方法之前執(zhí)行
  • @After注解修飾方法表示當前方法會在連接點之后執(zhí)行
  • @Around注解修飾方法表示當前方法會在連接點之前和之后均會執(zhí)行
  • @AfterThrowing注解修飾方法表示當前方法會在連接點拋異常之后執(zhí)行,如果不拋異常則不會執(zhí)行
  • @AfterReturning注解修飾方法表示當前方法會在連接點返回結果時執(zhí)行吼砂,如果連接點方法是void逆航,則該注解不會生效

@Pointcut后可以寫execution和@Annotation
execution表達式里的各個號的含義:
"execution(
com.zhlab..ssm.demo.web.controller.TestController.*(..))"

  • 返回類型: 第一個 * 號的位置:表示返回值類型,* 表示方法返回類型無限制
  • 包名以及類:表示需要攔截的包名渔肩,TestController指定了具體的類,如果這里改成 ..* 則表示controller包以及其子包下的所有類
  • 方法: 第二個 * 號 表示 所有方法因俐,后面括號里面表示方法的參數,兩個句點表示任何參數

annotation() 表達式:
"@annotation(org.springframework.web.bind.annotation.GetMapping)"
然后使用該切面的話周偎,就會切入注解是 @GetMapping的所有方法抹剩。這種方式很適合處理 @GetMapping、@PostMapping蓉坎、@DeleteMapping等不同注解有各種特定處理邏輯的場景澳眷。

  1. 在配置文件中加入aop配置信息如下
    <!-- 主要這個信息需要加在spring mvc配置文件里 -->
    <aop:aspectj-autoproxy></aop:aspectj-autoproxy>
  1. 啟動項目,然后訪問/test,效果如下:
aop demo

如果method有多個切面的話蛉艾,我們可以使用@Order(1) 來排序钳踊,數字越小排前面衷敌。
好了其他的例子就不一一例舉了。

很重要的AnnotationAwareAutoProxyCreator

小結

<aop:aspectj-autoproxy />標簽的作用是聲明自動為Spring容器中那些配置@Aspectj注解的切面的bean創(chuàng)建代理箍土,織入切面
這個標簽需要加到spring-mvc的配置代碼中才起作用
(頭部標簽聲明需要加入xmlns:aop="http://www.springframework.org/schema/aop"逢享,xsi:schemaLocation中需要加入:http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd)

原理

<aop:aspectj-autoproxy>標簽的解析
在前文《Spring源碼閱讀----Spring IoC之BeanFactory罐监、ApplicationContext》中我們介紹過parseBeanDefinitions方法中吴藻,會解析自定義標簽

    //xml解析過程中,調用了自定義標簽解析
    delegate.parseCustomElement(ele);

    //在BeanDefinitionParserDelegate類中執(zhí)行
    public BeanDefinition parseCustomElement(Element ele, @Nullable BeanDefinition containingBd) {
        // 注釋1 找到命名空間
        String namespaceUri = getNamespaceURI(ele);
        if (namespaceUri == null) {
            return null;
        }
        // 注釋2 根據命名空間找到對應的 NamespaceHandler
        NamespaceHandler handler = this.readerContext.getNamespaceHandlerResolver().resolve(namespaceUri);
        if (handler == null) {
            error("Unable to locate Spring NamespaceHandler for XML schema namespace [" + namespaceUri + "]", ele);
            return null;
        }
        // 注釋3 調用自定義的 NamespaceHandler 進行解析
        return handler.parse(ele, new ParserContext(this.readerContext, this, containingBd));
    }

    public BeanDefinitionHolder decorateBeanDefinitionIfRequired(Element ele, BeanDefinitionHolder definitionHolder) {
        return decorateBeanDefinitionIfRequired(ele, definitionHolder, null);
    }

會根據配置中的標簽命名空間 獲取 對應的NamespaceHandler弓柱,這里關注一下<aop:aspectj-autoproxy>標簽沟堡,它的handler是org.springframework.aop.config包下的AopNamespaceHandler:

public class AopNamespaceHandler extends NamespaceHandlerSupport {

    /**
     * Register the {@link BeanDefinitionParser BeanDefinitionParsers} for the
     * '{@code config}', '{@code spring-configured}', '{@code aspectj-autoproxy}'
     * and '{@code scoped-proxy}' tags.
     */
    @Override
    public void init() {
        // In 2.0 XSD as well as in 2.1 XSD.
        registerBeanDefinitionParser("config", new ConfigBeanDefinitionParser());
        // 注釋 自定義注解,注冊解析器矢空,元素名是 aspectj-autoproxy
        registerBeanDefinitionParser("aspectj-autoproxy", new AspectJAutoProxyBeanDefinitionParser());
        registerBeanDefinitionDecorator("scoped-proxy", new ScopedProxyBeanDefinitionDecorator());

        // Only in 2.0 XSD: moved to context namespace as of 2.1
        registerBeanDefinitionParser("spring-configured", new SpringConfiguredBeanDefinitionParser());
    }

}

AspectJAutoProxyBeanDefinitionParser類中關注parse方法:

    @Override
    public BeanDefinition parse(Element element, ParserContext parserContext) {
        // aop 注解的解析入口航罗,注冊 AnnotationAwareAspectJAutoProxyCreator
        AopNamespaceUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(parserContext, element);
        // 對注解中子類的處理
        extendBeanDefinition(element, parserContext);
        return null;
    }

繼續(xù)看看AopNamespaceUtils類中的registerAspectJAnnotationAutoProxyCreatorIfNecessary如何執(zhí)行的:

public static void registerAspectJAnnotationAutoProxyCreatorIfNecessary(
            ParserContext parserContext, Element sourceElement) {
        // 通過工具類,注冊或升級 AspectJAnnotationAutoProxyCreator
        BeanDefinition beanDefinition = AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(
                parserContext.getRegistry(), parserContext.extractSource(sourceElement));
        // 處理 proxy-target-class 以及 expose-proxy 屬性
        useClassProxyingIfNecessary(parserContext.getRegistry(), sourceElement);

        // 注冊AnnotationAwareAutoProxyCreator組件并通知屁药,讓監(jiān)聽器進行處理
        registerComponentIfNecessary(beanDefinition, parserContext);
    }

    private static void useClassProxyingIfNecessary(BeanDefinitionRegistry registry, @Nullable Element sourceElement) {
        if (sourceElement != null) {
            // 解析下面兩個屬性粥血,如果是 true,將它們加入代理注冊器的屬性列表中
            // definition.getPropertyValues().add("proxyTargetClass", Boolean.TRUE)
            boolean proxyTargetClass = Boolean.parseBoolean(sourceElement.getAttribute(PROXY_TARGET_CLASS_ATTRIBUTE));
            if (proxyTargetClass) {
                // 處理  proxy-target-class 屬性
                // 與代碼生成方式有關酿箭,在之后步驟中決定使用 jdk 動態(tài)代理 或 cglib
                AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);
            }
            boolean exposeProxy = Boolean.parseBoolean(sourceElement.getAttribute(EXPOSE_PROXY_ATTRIBUTE));
            if (exposeProxy) {
                // 處理 expose-proxy 屬性
                // 擴展增強复亏,有時候目標對象內部的自我調用無法實施切面中的增強,通過這個屬性可以同時對兩個方法進行增強
                AopConfigUtils.forceAutoProxyCreatorToExposeProxy(registry);
            }
        }
    }

    private static void registerComponentIfNecessary(@Nullable BeanDefinition beanDefinition, ParserContext parserContext) {
        if (beanDefinition != null) {
            // 注冊 的beanName 是 org.springframework.aop.config.internalAutoProxyCreator
            parserContext.registerComponent(
                    new BeanComponentDefinition(beanDefinition, AopConfigUtils.AUTO_PROXY_CREATOR_BEAN_NAME));
        }
    }

所以以上缭嫡,就是注冊AnnotationAwareAutoProxyCreator的過程缔御。aop中創(chuàng)建代理對象是通過AnnotationAwareAutoProxyCreator來實現的。

AnnotationAwareAutoProxyCreator

先來看看AnnotationAwareAutoProxyCreator的類圖妇蛀,如下:

AnnotationAwareAutoProxyCreator

可以看到它的父類AbstractAutoProxyCreator實現了BeanPostProcessor接口的子接口InstantiationAwareBeanPostProcessor耕突,這里關注AbstractAutoProxyCreator執(zhí)行的postProcessBeforeInstantiation方法和postProcessAfterInitialization方法。

postProcessBeforeInstantiation方法

@Override
    public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) {
        // 切面 bean 實例化之前執(zhí)行的方法
        // 根據beanClass和beanName獲取緩存的key
        Object cacheKey = getCacheKey(beanClass, beanName);

        // beanName 不存在 || 目標堆中不存在這個 bean
        if (!StringUtils.hasLength(beanName) || !this.targetSourcedBeans.contains(beanName)) {
            // 內層判斷是否需要進行切面增強评架,這是個短路操作眷茁,判斷成功后將跳過后面的操作
            if (this.advisedBeans.containsKey(cacheKey)) {
                return null;
            }
            if (isInfrastructureClass(beanClass) || shouldSkip(beanClass, beanName)) {
                this.advisedBeans.put(cacheKey, Boolean.FALSE);
                return null;
            }
        }

        // Create proxy here if we have a custom TargetSource.
        // Suppresses unnecessary default instantiation of the target bean:
        // The TargetSource will handle target instances in a custom fashion.
        // 如果我們有自定義 TargetSource,請在此處創(chuàng)建代理纵诞。
        // 禁止目標bean的不必要的默認實例化:
        // TargetSource將以自定義方式處理目標實例
        //TargetSource實例相當于就是目標對象bean的封裝實例
        TargetSource targetSource = getCustomTargetSource(beanClass, beanName);
        if (targetSource != null) {
            if (StringUtils.hasLength(beanName)) {
                this.targetSourcedBeans.add(beanName);
            }

            // 獲取當前bean所有的增強數組
            // 實際上委派給子類去實現 AbstractAdvisorAutoProxyCreator.getAdvicesAndAdvisorsForBean
            Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(beanClass, beanName, targetSource);
            // 根據增強數組為目標對象創(chuàng)建代理對象
            Object proxy = createProxy(beanClass, beanName, specificInterceptors, targetSource);
            this.proxyTypes.put(cacheKey, proxy.getClass());

            //返回代理bean
            return proxy;
        }

        return null;
    }


postProcessAfterInitialization方法

    @Override
    public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) {
        if (bean != null) {
            // 組裝 key
            Object cacheKey = getCacheKey(bean.getClass(), beanName);
            if (this.earlyProxyReferences.remove(cacheKey) != bean) {
                // 如果適合被代理蔼卡,則需要封裝指定的 bean
                return wrapIfNecessary(bean, beanName, cacheKey);
            }
        }
        return bean;
    }

wrapIfNecessary方法源碼:

protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
        // 如果已經處理過,直接返回
        if (StringUtils.hasLength(beanName) && this.targetSourcedBeans.contains(beanName)) {
            return bean;
        }
        // 不需增強挣磨,直接返回
        if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {
            return bean;
        }

        // 給定的 bean 類是否代表一個基礎設施類雇逞,基礎設置類不應代理
        //或者配置了指定 bean 不需要代理
        if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) {
            this.advisedBeans.put(cacheKey, Boolean.FALSE);
            return bean;
        }

        // Create proxy if we have advice.
        // 如果存在增強方法則創(chuàng)建代理
        //獲取當前bean所有的增強數組,也就是Advisor數組
        Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
        if (specificInterceptors != DO_NOT_PROXY) {
            // 增強方法不為空
            this.advisedBeans.put(cacheKey, Boolean.TRUE);

            // 創(chuàng)建代理
            Object proxy = createProxy(
                    bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
            this.proxyTypes.put(cacheKey, proxy.getClass());
            return proxy;
        }

        this.advisedBeans.put(cacheKey, Boolean.FALSE);
        return bean;
    }

createProxy方法創(chuàng)建代理對象

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

        // 創(chuàng)建代理工廠對象,并復制當前類的屬性
        ProxyFactory proxyFactory = new ProxyFactory();
        proxyFactory.copyFrom(this);

        // 決定對于給定 bean 是否應該使用 targetClass 而不是他的接口代理
        if (!proxyFactory.isProxyTargetClass()) {
            // 檢查 proxyTargetClass 設置以及 preserveTargetClass 屬性
            if (shouldProxyTargetClass(beanClass, beanName)) {
                proxyFactory.setProxyTargetClass(true);
            }
            else {
                // 添加代理接口
                evaluateProxyInterfaces(beanClass, proxyFactory);
            }
        }

        // 設置代理工廠屬性,將增強數組advisors和目標對象targetSource加入到代理工廠中
        Advisor[] advisors = buildAdvisors(beanName, specificInterceptors);
        proxyFactory.addAdvisors(advisors);
        proxyFactory.setTargetSource(targetSource);

        // 自定義定制代理
        customizeProxyFactory(proxyFactory);

        // 用來控制代理工廠被配置之后,是否含允許修改通知
        // 缺省值為 false茁裙,不允許修改代理的配置
        proxyFactory.setFrozen(this.freezeProxy);
        if (advisorsPreFiltered()) {
            proxyFactory.setPreFiltered(true);
        }
        // 調用代理工廠類的getProxy方法創(chuàng)建代理對象
        return proxyFactory.getProxy(getProxyClassLoader());
    }

通過代碼執(zhí)行過程塘砸,我們可以發(fā)現是委托給ProxyFactory來創(chuàng)建代理對象的。
ProxyFactory的getProxy方法源碼:

    public Object getProxy(@Nullable ClassLoader classLoader) {
        return createAopProxy().getProxy(classLoader);
    }

    //創(chuàng)建AopProxy對象
    protected final synchronized AopProxy createAopProxy() {
        if (!this.active) {
            activate();
        }
        return getAopProxyFactory().createAopProxy(this);
    }

先是createAopProxy創(chuàng)建AopProxy對象 晤锥,然后通過getProxy獲取代理對象
那先來看DefaultAopProxyFactory類中的createAopProxy方法:

    @Override
    public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {

        // 創(chuàng)建代理
        //這里有兩種代理類型 1. JDK 動態(tài)代理 2. CGLIB 動態(tài)代理
        // isOptimize 判斷是否采用優(yōu)化策略
        //isProxyTargetClass: 該屬性對于<aop:aspectj-autoproxy/>標簽中的proxy-target-class屬性的值.表示是否代理目標類本身,而不是目標類的接口
        //hasNoUserSuppliedProxyInterfaces :判斷是否存在代理接口
        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.");
            }

            //如果目標對象是一個接口,則創(chuàng)建JDK動態(tài)代理對象 
            if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) {
                return new JdkDynamicAopProxy(config);
            }

            //如果目標對象不是一個接口,則創(chuàng)建 CGLIB代理對象
            return new ObjenesisCglibAopProxy(config);
        }
        else {
            //創(chuàng)建JDK動態(tài)代理對象 
            return new JdkDynamicAopProxy(config);
        }
    }

如何選擇JDK動態(tài)代理(JdkDynamicAopProxy )還是CGLIB代理(ObjenesisCglibAopProxy)?

  • 如果目標對象實現了接口掉蔬,默認情況下會采用JDK動態(tài)代理廊宪;但是可以通過配置 proxy-target-class屬性的值為true強制使用CGLIB代理,則代理的是目標對象的本身
  • 如果目標對象沒有實現接口女轿,那么必須采用CGLIB創(chuàng)建代理對象
    JdkDynamicAopProxy 源碼:
final class JdkDynamicAopProxy implements AopProxy, InvocationHandler, Serializable {

     //....前面省略

    //JdkDynamicAopProxy 構造函數,設置配置信息
    public JdkDynamicAopProxy(AdvisedSupport config) throws AopConfigException {
        Assert.notNull(config, "AdvisedSupport must not be null");
        if (config.getAdvisors().length == 0 && config.getTargetSource() == AdvisedSupport.EMPTY_TARGET_SOURCE) {
            throw new AopConfigException("No advisors and no TargetSource specified");
        } else {
            this.advised = config;
        }
    }

    //創(chuàng)建代理對象
    public Object getProxy() {
        return this.getProxy(ClassUtils.getDefaultClassLoader());
    }

    public Object getProxy(@Nullable ClassLoader classLoader) {
        if (logger.isTraceEnabled()) {
            logger.trace("Creating JDK dynamic proxy: " + this.advised.getTargetSource());
        }

        Class<?>[] proxiedInterfaces = AopProxyUtils.completeProxiedInterfaces(this.advised, true);
        this.findDefinedEqualsAndHashCodeMethods(proxiedInterfaces);

        // Proxy.newProxyInstance 動態(tài)代理創(chuàng)建對象
        return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this);
    }

    // 這個熟悉不箭启?因為實現了InvocationHandler接口,所以要重新invoke方法
    @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 {
            // 處理 equals 方法
            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.
            // 檢查我們是否有任何切面邏輯蛉迹。如果我們不這樣做傅寡,我們可以回退直接反射調用目標,并避免創(chuàng)建 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...
                // 將攔截器封裝在 ReflectiveMethodInvocation荐操,便于使用 proceed 執(zhí)行攔截器
                invocation = new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain);
                // Proceed to the joinpoint through the interceptor chain.
                // 執(zhí)行攔截器鏈
                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);
            }
        }
    }

    //....后面省略
}

ObjenesisCglibAopProxy繼承于CglibAopProxy類,其代理對象創(chuàng)建在CglibAopProxy類中實現:

    @Override
    public Object getProxy() {

        // 不傳ClassLoader 
        return getProxy(null);
    }

    @Override
    public Object getProxy(@Nullable ClassLoader classLoader) {
        if (logger.isTraceEnabled()) {
            logger.trace("Creating CGLIB proxy: " + this.advised.getTargetSource());
        }

        try {
            Class<?> rootClass = this.advised.getTargetClass();
            Assert.state(rootClass != null, "Target class must be available for creating a CGLIB proxy");

            Class<?> proxySuperClass = rootClass;
            if (rootClass.getName().contains(ClassUtils.CGLIB_CLASS_SEPARATOR)) {
                proxySuperClass = rootClass.getSuperclass();
                Class<?>[] additionalInterfaces = rootClass.getInterfaces();
                for (Class<?> additionalInterface : additionalInterfaces) {
                    this.advised.addInterface(additionalInterface);
                }
            }

            // Validate the class, writing log messages as necessary.
            validateClassIfNecessary(proxySuperClass, classLoader);

            // Configure CGLIB Enhancer...
            // 創(chuàng)建CGLIB  Enhancer對象,并設置Enhancer對象的各種屬性
            Enhancer enhancer = createEnhancer();
            if (classLoader != null) {
                enhancer.setClassLoader(classLoader);
                if (classLoader instanceof SmartClassLoader &&
                        ((SmartClassLoader) classLoader).isClassReloadable(proxySuperClass)) {
                    enhancer.setUseCache(false);
                }
            }
            enhancer.setSuperclass(proxySuperClass);
            enhancer.setInterfaces(AopProxyUtils.completeProxiedInterfaces(this.advised));
            enhancer.setNamingPolicy(SpringNamingPolicy.INSTANCE);
            enhancer.setStrategy(new ClassLoaderAwareUndeclaredThrowableStrategy(classLoader));

            Callback[] callbacks = getCallbacks(rootClass);
            Class<?>[] types = new Class<?>[callbacks.length];
            for (int x = 0; x < types.length; x++) {
                types[x] = callbacks[x].getClass();
            }
            // fixedInterceptorMap only populated at this point, after getCallbacks call above
            enhancer.setCallbackFilter(new ProxyCallbackFilter(
                    this.advised.getConfigurationOnlyCopy(), this.fixedInterceptorMap, this.fixedInterceptorOffset));
            enhancer.setCallbackTypes(types);

            // Generate the proxy class and create a proxy instance.
            // 調用createProxyClassAndInstance方法創(chuàng)建代理對象
            return createProxyClassAndInstance(enhancer, callbacks);
        }
        catch (CodeGenerationException | IllegalArgumentException ex) {
            throw new AopConfigException("Could not generate CGLIB subclass of " + this.advised.getTargetClass() +
                    ": Common causes of this problem include using a final class or a non-visible class",
                    ex);
        }
        catch (Throwable ex) {
            // TargetSource.getTarget() failed
            throw new AopConfigException("Unexpected AOP exception", ex);
        }
    }

    protected Object createProxyClassAndInstance(Enhancer enhancer, Callback[] callbacks) {
        enhancer.setInterceptDuringConstruction(false);
        enhancer.setCallbacks(callbacks);

        //執(zhí)行Enhancer的create方法創(chuàng)建代理對象
        return (this.constructorArgs != null && this.constructorArgTypes != null ?
                enhancer.create(this.constructorArgTypes, this.constructorArgs) :
                enhancer.create());
    }

CGLIB 是一套強大的高性能的代碼生成工具包珍策,底層通過字節(jié)碼生成技術ASM框架來實現
什么是CGLIB,參考這篇文章《CGLIB動態(tài)代理的實現及原理》

從ObjenesisCglibAopProxy創(chuàng)建代理的對象的步驟可以看到:
最終是由Enhancer 對象來創(chuàng)建代理的,傳入的Callback數組托启,可以是實現了MethodInterceptor接口,并重寫intercept的攔截器對象攘宙。
每次代理對象執(zhí)行方法屯耸,會執(zhí)行Callback的intercept方法,會通過執(zhí)行invokeSuper方法來執(zhí)行目標類的方法蹭劈。

總結

好了疗绣,到這里我們就算完成了對Spring AOP的了解以及原理的分析。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
  • 序言:七十年代末链方,一起剝皮案震驚了整個濱河市持痰,隨后出現的幾起案子,更是在濱河造成了極大的恐慌祟蚀,老刑警劉巖工窍,帶你破解...
    沈念sama閱讀 207,248評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現場離奇詭異前酿,居然都是意外死亡患雏,警方通過查閱死者的電腦和手機,發(fā)現死者居然都...
    沈念sama閱讀 88,681評論 2 381
  • 文/潘曉璐 我一進店門罢维,熙熙樓的掌柜王于貴愁眉苦臉地迎上來淹仑,“玉大人,你說我怎么就攤上這事肺孵≡冉瑁” “怎么了?”我有些...
    開封第一講書人閱讀 153,443評論 0 344
  • 文/不壞的土叔 我叫張陵平窘,是天一觀的道長吓肋。 經常有香客問我,道長瑰艘,這世上最難降的妖魔是什么是鬼? 我笑而不...
    開封第一講書人閱讀 55,475評論 1 279
  • 正文 為了忘掉前任肤舞,我火速辦了婚禮,結果婚禮上均蜜,老公的妹妹穿的比我還像新娘李剖。我一直安慰自己,他們只是感情好囤耳,可當我...
    茶點故事閱讀 64,458評論 5 374
  • 文/花漫 我一把揭開白布篙顺。 她就那樣靜靜地躺著,像睡著了一般紫皇。 火紅的嫁衣襯著肌膚如雪慰安。 梳的紋絲不亂的頭發(fā)上腋寨,一...
    開封第一講書人閱讀 49,185評論 1 284
  • 那天聪铺,我揣著相機與錄音,去河邊找鬼萄窜。 笑死铃剔,一個胖子當著我的面吹牛,可吹牛的內容都是我干的查刻。 我是一名探鬼主播键兜,決...
    沈念sama閱讀 38,451評論 3 401
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼穗泵!你這毒婦竟也來了普气?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 37,112評論 0 261
  • 序言:老撾萬榮一對情侶失蹤佃延,失蹤者是張志新(化名)和其女友劉穎现诀,沒想到半個月后,有當地人在樹林里發(fā)現了一具尸體履肃,經...
    沈念sama閱讀 43,609評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡仔沿,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 36,083評論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現自己被綠了尺棋。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片封锉。...
    茶點故事閱讀 38,163評論 1 334
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖膘螟,靈堂內的尸體忽然破棺而出成福,到底是詐尸還是另有隱情,我是刑警寧澤荆残,帶...
    沈念sama閱讀 33,803評論 4 323
  • 正文 年R本政府宣布奴艾,位于F島的核電站,受9級特大地震影響脊阴,放射性物質發(fā)生泄漏握侧。R本人自食惡果不足惜蚯瞧,卻給世界環(huán)境...
    茶點故事閱讀 39,357評論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望品擎。 院中可真熱鬧埋合,春花似錦、人聲如沸萄传。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,357評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽秀菱。三九已至振诬,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間衍菱,已是汗流浹背赶么。 一陣腳步聲響...
    開封第一講書人閱讀 31,590評論 1 261
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留脊串,地道東北人辫呻。 一個月前我還...
    沈念sama閱讀 45,636評論 2 355
  • 正文 我出身青樓,卻偏偏與公主長得像琼锋,于是被迫代替她去往敵國和親放闺。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 42,925評論 2 344

推薦閱讀更多精彩內容