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

概述

Spring經(jīng)常被人提及的就是IOC和AOP,前邊在介紹IOC的時候,我們已經(jīng)提及到了AOP,還記得起來嗎?
在《Spring源碼閱讀----Spring IoC之finishBeanFactoryInitialization(續(xù))很重要的createBean》一文中,介紹到有些實現(xiàn)了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包以及其子包下的所有類
  • 方法: 第二個 * 號 表示 所有方法,后面括號里面表示方法的參數(shù),兩個句點表示任何參數(shù)

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) 來排序,數(shù)字越小排前面。
好了其他的例子就不一一例舉了。

很重要的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 根據(jù)命名空間找到對應的 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);
    }

會根據(jù)配置中的標簽命名空間 獲取 對應的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來實現(xiàn)的。

AnnotationAwareAutoProxyCreator

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

AnnotationAwareAutoProxyCreator

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

postProcessBeforeInstantiation方法

@Override
    public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) {
        // 切面 bean 實例化之前執(zhí)行的方法
        // 根據(jù)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所有的增強數(shù)組
            // 實際上委派給子類去實現(xiàn) AbstractAdvisorAutoProxyCreator.getAdvicesAndAdvisorsForBean
            Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(beanClass, beanName, targetSource);
            // 根據(jù)增強數(shù)組為目標對象創(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) {
        // 如果已經(jīng)處理過,直接返回
        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所有的增強數(shù)組,也就是Advisor數(shù)組
        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);
            }
        }

        // 設置代理工廠屬性,將增強數(shù)組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ā)現(xiàn)是委托給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)?

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

     //....前面省略

    //JdkDynamicAopProxy 構造函數(shù),設置配置信息
    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);
    }

    // 這個熟悉不?因為實現(xiàn)了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類中實現(xiàn):

    @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框架來實現(xiàn)
什么是CGLIB,參考這篇文章《CGLIB動態(tài)代理的實現(xiàn)及原理》

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

總結

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

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內容

友情鏈接更多精彩內容