spring源碼系列8:AOP源碼解析之代理的建立

回顧

首先回顧:java

JDK動態代理與CGLIB動態代理spring

Spring中的InstantiationAwareBeanPostProcessor和BeanPostProcessor的區別數組

咱們得知 JDK動態代理兩要素:Proxy+InvocationHandler CGLB動態代理兩要素:Enhancer + MethodInterceptor(Callback)緩存

springAOP底層是經過動態代理和CGLB代理實現的。也就是spring最終的落腳點還應該是在Proxy+InvocationHandler 或者Enhancer + MethodInterceptor上。springboot

帶着這個期待咱們看看spring是如何組織AOP的,並在動態代理之上創建一個AOP體系的。bash

概念的理解:

  • 通知: 通知能夠理解加強器, 就是作的額外工做.
  • 鏈接點: 能夠容許切面插入的點, 這個點能夠是方法調用時, 拋出異常時等.
  • 切點: 並非全部的鏈接點都須要被切面插入, 切點就是定義哪些鏈接點能夠插入切面.

總結爲:從全部鏈接點中選出部分鏈接點, 進行攔截,執行額外操做。框架

組件的理解:

AOP最先由AOP聯盟的組織提出的,制定了一套規範.Spring將AOP思想引入到框架中,必須遵照AOP聯盟的規範.ide

注意:各類組件很是之多. 我只把自認爲涉及到主線理解的組件列出工具


AOP聯盟規範定義組件

通知(加強器): 不要糾結於太多. 就統一理解爲攔截器或者加強器。post

file

注意一點:這裏的MethodInterceptor區別於上文提到的
org.springframework.cglib.proxy.MethodInterceptor不要混了。
複製代碼

鏈接點(被攔截):spring大多都是對方法調用的攔截, 這裏能夠理解爲方法調用.

file


spring定義組件

1.Pointcut定義哪些鏈接點能夠插入切面。提供ClassFilter 與MethodMatcher兩種匹配器,匹配鏈接點。

2.Advisor : 包裝Advice和Pointcut .語義: 在哪裏攔截, 插入什麼樣的加強器(在哪裏作什麼)Advisor=Advice+Pointcut 分爲

  • IntroductionAdvisor: 引介加強,在不修改某個類的狀況下, 讓其具有某接口的功能。
  • PointcutAdvisor: 與切點有關的Advisor

3.TargetSource: 對目標對象的封裝。

4.Advised接口 : 包裝 Advisor 與 TargetSource。 實現類AdvisedSupport:從其兩個屬性上,真切看出其封裝了 Advisor 與 TargetSource

  • TargetSource targetSource = EMPTY_TARGET_SOURCE; 表示目標對象
  • private List advisors = new ArrayList(); 存儲Advisor

5.AopProxyAOP代理對象

  • 分JDK代理(JdkDynamicAopProxy)
  • Cglib代理(CglibAopProxy)
    在這裏插入圖片描述

JdkDynamicAopProxy與CglibAopProxy都實現了AopProxy的getProxy()方法,用於返回真正的代理對象。

6.AopProxyFactoryAOP代理策略工廠類。根據條件選擇使用JDK仍是Cglib的方式來建立代理對象。

file

7.ProxyCreatorSupport: 從其語義上理解,對建立代理對象的支持。咱們從其繼承關係上看看他是如何提供支持的。

  • ProxyConfig: 提供aop配置屬性。
  • AdvisedSupport:繼承ProxyConfig,實現了Advised接口。封裝通知(Advise)和TargetSource,並提供對他們的操做
  • ProxyCreatorSupport: 包含AopProxyFactory,AopProxyFactory策略工廠提供對JdkDynamicAopProxy與CglibAopProxy的建立

file

8.AbstractAutoProxyCreator: 從其繼承關係。咱們分析下這個組件。

  • 首先他是一個(BeanPostProcessor)InstantiationAwareBeanPostProcessor 因此他會在spring的Bean生產線createBean()過程當中被執行。在BeanDefinition建立Bean的過程當中進行攔截,根據要求建立出代理對象。
  • Aware: 能夠獲取到BeanFactory倉庫, 與BeanClassLoader加載器。
  • ProxyCreatorSupport,繼承了建立代理的功能。

關於BeanPostProcessor與InstantiationAwareBeanPostProcessor的理解,仍是深入理解Spring中的InstantiationAwareBeanPostProcessor和BeanPostProcessor的區別

file

小結

若是總結下組件之間的關係:

開發人員定義切面信息--》spring解析出Advice,切點等配置信息--》AopProxyFactory根據配置建立代理對象--》代理方法執行。

這也是springAOP大部分工做內容。

籠統來看:

  • 《1》定義的解析:
  • 《2》代理的建立:
  • 《3》代理的執行:

下面咱們重點看看定義的解析與代理的建立。

代理的生成過程:

代理的執行過程: 咱們仍是以springboot環境下的AOP實現來說講AOP的過程.

1.配置AOP的擴展器,攔截BeanDefiniiton建立Bean的過程:AnnotationAwareAspectJAutoProxyCreator:

首先配置AOP環境

@EnableAspectJAutoProxy註解上的@Import(AspectJAutoProxyRegistrar.class)引入AspectJAutoProxyRegistrar類.AspectJAutoProxyRegistrar實現了ImportBeanDefinitionRegistrar接口. 因此其registerBeanDefinitions()會有一些注入BeanDefiniiton的操做 . registerBeanDefinitions()方法會向倉庫中注入一個AnnotationAwareAspectJAutoProxyCreator.

@Override
	public void registerBeanDefinitions( AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {

//注入AnnotationAwareAspectJAutoProxyCreator擴展器
		AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry);

		AnnotationAttributes enableAspectJAutoProxy =
				AnnotationConfigUtils.attributesFor(importingClassMetadata, EnableAspectJAutoProxy.class);
		if (enableAspectJAutoProxy.getBoolean("proxyTargetClass")) {
			AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);
		}
		if (enableAspectJAutoProxy.getBoolean("exposeProxy")) {
			AopConfigUtils.forceAutoProxyCreatorToExposeProxy(registry);
		}
	}
複製代碼

AnnotationAwareAspectJAutoProxyCreator 間接繼承了AOP擴展工具AbstractAutoProxyCreator, 是一個BeanPostProcessor。

AbstractAutoProxyCreator:

  • 是一個BeanPostProcessor,能夠攔截Bean建立過程
  • 繼承了ProxyCreatorSupport具備代理類的建立能力。

這樣:AOP環境有了。

2.攔截生產過程,建立AOP對象:

createBean()生產線在建立Bean的過程當中. 會執行全部的BeanPostProcessor. AnnotationAwareAspectJAutoProxyCreator(AbstractAutoProxyCreator)做爲一個BeanPostProcessor也在此時執行.

Spring中的InstantiationAwareBeanPostProcessor和BeanPostProcessor的區別 講過. 實現了InstantiationAwareBeanPostProcessor接口的BeanPostProcessor的會有5個方法伴隨Bean建立過程且執行順序。 postProcessBeforeInstantiation() -->postProcessAfterInstantiation-->postProcessPropertyValues-->postProcessBeforeInitialization()-->postProcessAfterInitialization()

過程:

(2.1)首先執行的是postProcessBeforeInstantiation 實例化前置處理方法

@Override
	public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
		Object cacheKey = getCacheKey(beanClass, beanName);
		if (beanName == null || !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;
			}
		}
		if (beanName != null) {
			TargetSource targetSource = getCustomTargetSource(beanClass, beanName);
			if (targetSource != null) {
				this.targetSourcedBeans.add(beanName);
				Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(beanClass, beanName, targetSource);
				Object proxy = createProxy(beanClass, beanName, specificInterceptors, targetSource);
				this.proxyTypes.put(cacheKey, proxy.getClass());
				return proxy;
			}
		}
		return null;
	}
複製代碼

主要分爲兩部分: (2.1.1)先判斷是否應該代理

  • isInfrastructureClass(beanClass)若是是AOP基礎設施類, 不代理。指的是Advice、Pointcut、Advisor等AOP相關定義類不該該建立代理
  • shouldSkip()應該跳過的類,不代理。判斷的依據:默認是都不跳過的. 子類可能重寫其判斷依據.AnnotationAwareAspectJAutoProxyCreator的父類AnnotationAwareAspectJAutoProxyCreator重寫了shouldSkip方法(《1》並伴隨切面定義的解析)。

重點看看shouldSkip()

/* 1.首先查找適於當前Bean的Advisor .通findCandidateAdvisors()去查找 findCandidateAdvisors()會通過兩個渠道獲取Advisors. > BeanFactoryAdvisorRetrievalHelper.findAdvisorBeans():是從倉庫中找實現了Advisor類的Advisor > BeanFactoryAspectJAdvisorsBuilder.buildAspectJAdvisors()會從倉庫中取出@Aspect註解的切面類,解析出Advisor 重點說一下其中buildAspectJAdvisors >遍歷BeanFactory倉庫中的BeanDefinition,根據其類型判斷其是不是isAspect(): 判斷條件是類是否被@Aspect註釋,而且沒有被aspectj編譯過 >若是是, 根據當前BeanDefinition建立一個(AspectJAdvisorFactory)BeanFactoryAspectInstanceFactory工廠對象. >使用AspectJAdvisorFactory 工廠建立List<Advisor> >上文已經說過Advisor=Advice+Pointcut, Advice 就是對通知的封裝(@Before...), Pointcut 是對切點的封裝. 小結:此次知道咱們定義一個切面類, 被解析什麼樣子了吧 2.判斷找到的CandidateAdvisors中有沒有當前BeanDefinition,有的話就跳過。 */
@Override
	protected boolean shouldSkip(Class<?> beanClass, String beanName) {
		// TODO: Consider optimization by caching the list of the aspect names
		List<Advisor> candidateAdvisors = findCandidateAdvisors();
		for (Advisor advisor : candidateAdvisors) {
			if (advisor instanceof AspectJPointcutAdvisor) {
				if (((AbstractAspectJAdvice) advisor.getAdvice()).getAspectName().equals(beanName)) {
					return true;
				}
			}
		}
		return super.shouldSkip(beanClass, beanName);
	}
複製代碼

(2.1.2) 判斷是否有自定義的 TargetSource。 若是有自定義TargetSource ,將當前beanName放入targetSourcedBeans緩存中,直接走建立代理的分支,不會走createBean去建立Bean,這裏就是給一個機會。 關於自定義TargetSource這個分支暫時不講。

if (beanName != null) {
			TargetSource targetSource = getCustomTargetSource(beanClass, beanName);
			if (targetSource != null) {
				this.targetSourcedBeans.add(beanName);
				Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(beanClass, beanName, targetSource);
				Object proxy = createProxy(beanClass, beanName, specificInterceptors, targetSource);
				this.proxyTypes.put(cacheKey, proxy.getClass());
				return proxy;
			}
		}
複製代碼

總結postProcessBeforeInstantiation工做內容:

  • 解析切面定義
  • 提供一個機會直接返回代理對象,不走createBean()流水線。自定義TargetSource

(2.2)postProcessAfterInstantiation

  • return true ;

(2.3)postProcessBeforeInitialization

  • 返回Bean沒有作處理

(2.4)postProcessAfterInitialization() (敲黑板,重點

public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
		if (bean != null) {
			Object cacheKey = getCacheKey(bean.getClass(), beanName);
			if (this.earlyProxyReferences.remove(cacheKey) != bean) {
				return wrapIfNecessary(bean, beanName, cacheKey);
			}
		}
		return bean;
	}
複製代碼

關鍵便在於wrapIfNecessary方法: 名字 wrap if Necessary 若是知足條件包裝 這個方法就能夠拆成兩部分看:

  1. 知足條件:
  2. 包裝:
protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
		//1.自定義TargetSource,已經進行過代理子類生成 。 不包裝直接返回Bean實例
		if (beanName != null && this.targetSourcedBeans.contains(beanName)) {
			return bean;
		}
		//2.已經斷定不須要代理的, 不代理
		if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {
			return bean;
		}
		//3.isInfrastructureClass(bean.getClass())是基礎設施類的不代理
		//4.shouldSkip(bean.getClass(), beanName)應該跳過的不代理
		if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) {
			this.advisedBeans.put(cacheKey, Boolean.FALSE);
			return bean;
		}

		// 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;
		}
		//5.沒有具體攔截器的不代理
		this.advisedBeans.put(cacheKey, Boolean.FALSE);
		return bean;
	}
複製代碼

咱們挨個分析下這兩部分


(2.4.1) 知足條件

不代理的狀況

  • 自定義TargetSource,已經進行過代理子類生成 。 不包裝直接返回Bean實例。()
  • 已經斷定不須要代理的, 不代理。 直接返回Bean實例
  • isInfrastructureClass(bean.getClass())是基礎設施類的不代理。 (上文已經提過)
  • shouldSkip(bean.getClass(), beanName)應該跳過的不代理 (上文已經提過)
  • 沒有具體攔截器的不代理

代理的的狀況

  • 有具體Advice的才代理:getAdvicesAndAdvisorsForBean() 的返回不爲空的。(Create proxy if we have advice.)

Advisor尋找:重點就落在了此處。

即getAdvicesAndAdvisorsForBean方法,這裏進行的即是去容器中尋找適用於當前bean的Advisor,最終調用的是

AbstractAdvisorAutoProxyCreator.findEligibleAdvisors:

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;
	}
複製代碼
  • findCandidateAdvisors: 獲取全部Advisor ,前面已經說過。 由於作了緩存此處直接從緩存中取。

  • findAdvisorsThatCanApply: 看其傳入的參數,candidateAdvisors(全部的候選Advisor), 也就是這個方法確定就是從全部的候選Advisor找出適合當前Bean

  • extendAdvisors: 容許子類添加advisor

適用性判斷 findAdvisorsThatCanApply最終調用AopUtils.findAdvisorsThatCanApply:

public static List<Advisor> findAdvisorsThatCanApply(List<Advisor> candidateAdvisors, Class<?> clazz) {
		if (candidateAdvisors.isEmpty()) {
			return candidateAdvisors;
		}
		List<Advisor> eligibleAdvisors = new LinkedList<Advisor>();
		//第一遍
		for (Advisor candidate : candidateAdvisors) {
			if (candidate instanceof IntroductionAdvisor && canApply(candidate, clazz)) {
				eligibleAdvisors.add(candidate);
			}
		}
		//第一遍
		boolean hasIntroductions = !eligibleAdvisors.isEmpty();
		for (Advisor candidate : candidateAdvisors) {
			if (candidate instanceof IntroductionAdvisor) {
				// already processed
				continue;
			}
			if (canApply(candidate, clazz, hasIntroductions)) {
				eligibleAdvisors.add(candidate);
			}
		}
		return eligibleAdvisors;
	}
複製代碼

此方法有兩個for循環。 第一個for循環尋找IntroductionAdvisor(引介加強)類型的advisor,調用AopUtils.canApply 第二遍for循環尋找普通的advisor,調用AopUtils.canApply

AopUtils.canApply針對兩種類型的Advisor作了不一樣的判斷:

  • 針對IntroductionAdvisor類型advisor的,只須要校驗Advisor的ClassFilter是否匹配當前類
  • 針對普通的advisor:(1)首先查看定的類是否在Pointcut的匹配範圍內;(2)是的話,再查看是否能匹配此類任意方法,是的話返回true;(3)不能匹配任意方法,便會用反射的方法獲取targetClass(被檢測類)的所有方法逐一交由Pointcut的MethodMatcher.matches方法進行檢測。
public static boolean canApply(Pointcut pc, Class<?> targetClass, boolean hasIntroductions) {
		Assert.notNull(pc, "Pointcut must not be null");
		if (!pc.getClassFilter().matches(targetClass)) {
			return false;
		}
		//是否配置任意方法
		MethodMatcher methodMatcher = pc.getMethodMatcher();
		if (methodMatcher == MethodMatcher.TRUE) {
			// No need to iterate the methods if we're matching any method anyway...
			return true;
		}

		IntroductionAwareMethodMatcher introductionAwareMethodMatcher = null;
		if (methodMatcher instanceof IntroductionAwareMethodMatcher) {
			introductionAwareMethodMatcher = (IntroductionAwareMethodMatcher) methodMatcher;
		}
		//逐一排查
		Set<Class<?>> classes = new LinkedHashSet<Class<?>>(ClassUtils.getAllInterfacesForClassAsSet(targetClass));
		classes.add(targetClass);
		for (Class<?> clazz : classes) {
			Method[] methods = ReflectionUtils.getAllDeclaredMethods(clazz);
			for (Method method : methods) {
				if ((introductionAwareMethodMatcher != null &&
						introductionAwareMethodMatcher.matches(method, targetClass, hasIntroductions)) ||
						methodMatcher.matches(method, targetClass)) {
					return true;
				}
			}
		}

		return false;
	}
複製代碼

到此,AopUtils.canApply返回true後。findAdvisorsThatCanApply()算是找到了能應用於當前類的Advisors. 再extendAdvisors後;對,應用於當前類的Advisors一番排序後,getAdvicesAndAdvisorsForBean工做完成。

getAdvicesAndAdvisorsForBean()返回若是不爲Null。那下面就是包裝。


(2.4.2) 包裝 在getAdvicesAndAdvisorsForBean返回advisors不爲null後,能夠建立代理。

protected Object createProxy( Class<?> beanClass, String beanName, Object[] specificInterceptors, TargetSource targetSource) {
		ProxyFactory proxyFactory = new ProxyFactory();
		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());
	}
複製代碼
  • 首先建立ProxyFactory 工廠,從AbstractAutoProxyCreator複製代理屬性,由於AbstractAutoProxyCreator繼承了ProxyConfig,因此自己也是一個代理配置類。
  • 判斷其是基於類代理, 仍是基於接口代理。若是基於接口代理,獲取接口,並設置到ProxyFactory 。
  • buildAdvisors()方法,整合getAdvicesAndAdvisorsForBean找的advisors 與AbstractAutoProxyCreator. interceptorNames屬性可能設置的加強器,統一包裝成Advisor類型數組,設置到ProxyFactory 。而且AbstractAutoProxyCreator. interceptorNames屬性設置的加強器在前。
  • customizeProxyFactory(proxyFactory); 子類能夠繼續處理ProxyFactory
  • 設置ProxyFactory的Frozen屬性
  • setPreFiltered設置ProxyFactory 的preFiltered
  • getProxy 返回代理對象

咱們能夠看出,這裏兩大部分:

(1)建立proxyFactory工廠,並配置工廠

(2)proxyFactory.getProxy(getProxyClassLoader())返回代理對象。

proxyFactory.getProxy(ClassLoader classLoader)

proxyFactory.getProxy(ClassLoader classLoader) 首先會先建立一個默認的策略工廠DefaultAopProxyFactory。DefaultAopProxyFactory 會根據proxyFactory是基於接口的代理仍是基於類的代理,選擇建立JdkDynamicAopProxy對象,或者建立一個CglibAopProxy對象

這裏有必要介紹下DefaultAopProxyFactory.createAopProxy方法,此方法用來判斷是JDK代理,仍是CGLB代理。

if (config.isOptimize() //是否對代理類的生成使用策略優化
    || config.isProxyTargetClass() //設置proxy-target-class="true
    || hasNoUserSuppliedProxyInterfaces(config)) {//目標類是否有接口存在 且只有一個接口的時候接口類型不是
        //SpringProxy類型 
			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.");
			}
			//判斷目標類是不是接口 若是目標類是接口的話,則仍是使用JDK的方式生成代理對象
            //若是目標類是Proxy類型 則仍是使用JDK的方式生成代理對象
			if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) {
				return new JdkDynamicAopProxy(config);
			}
			//CGLB代理。
			return new ObjenesisCglibAopProxy(config);
		}
		else {
		    //JDK代理
			return new JdkDynamicAopProxy(config);
		}
複製代碼

咱們能夠看出高版本的會根據設置和目標類的實際狀況選擇使用CGLB或者JDK代理。也就是說,設置了proxy-target-class="true"不必定就是使用CGLB,而是根據實際狀況定。具體版本具體對待。

JdkDynamicAopProxy.getProxy()或者CglibAopProxygetProxy()纔是真正返回代理對象。


再次回顧JDK動態代理與CGLIB動態代理

JdkDynamicAopProxy.getProxy()

@Override
	public Object getProxy(ClassLoader classLoader) {
		if (logger.isDebugEnabled()) {
			logger.debug("Creating JDK dynamic proxy: target source is " + this.advised.getTargetSource());
		}
		Class<?>[] proxiedInterfaces = AopProxyUtils.completeProxiedInterfaces(this.advised, true);
		findDefinedEqualsAndHashCodeMethods(proxiedInterfaces);
		return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this);
	}
複製代碼

咱們看到JDK動態代理的兩個要素: Proxy+InvocationHandler InvocationHandler 此時就是JdkDynamicAopProxy,同時JdkDynamicAopProxy封裝了advised。這樣完美的把advised與JDK動態代理聯繫在了一塊兒

接下來就是在內存中生成一個字節碼JDK代理類$Proxy66.class,生成真正的代理對象了。

CglibAopProxygetProxy() (省略部分源碼,直奔主題)

// Configure CGLIB Enhancer...
			Enhancer enhancer = createEnhancer();
			Callback[] callbacks = getCallbacks(rootClass);
			enhancer.setInterfaces(AopProxyUtils.completeProxiedInterfaces(this.advised));
			return createProxyClassAndInstance(enhancer, callbacks);
		}
		
複製代碼

咱們看到了Cglb熟悉的要素Enhancer 。MethodInterceptor去哪了呢?

跟進getCallbacks()方法,會發現此方法會建立一個DynamicAdvisedInterceptor。DynamicAdvisedInterceptor實現了MethodInterceptor,並封裝了advisors。

Callback aopInterceptor = new DynamicAdvisedInterceptor(this.advised);
複製代碼

這樣,CGLB動態代理完美的與advised結合在了一塊兒。 接下來就是在內存中生成一個新的字節碼CGLB代理類***$$FastClassByCGLIB$$29e52466,並生成真實代理對象了。

總結

springaop 底層仍是JDK動態代理,CGLB動態代理。經過把加強器封裝到Advised中,把Advised與InvocationHandler或者MethodInterceptor聯繫起來,完美的實現AOP技術

都說事務是根據AOP實現的,趁熱打鐵,看看事務是如何建立代理的?敬請期待 歡迎你們關注個人公衆號【源碼行動】,最新我的理解及時奉送。

在這裏插入圖片描述
相關文章
相關標籤/搜索