1. 程式人生 > 其它 >淺析:AOP的advice和advisor建立過程

淺析:AOP的advice和advisor建立過程

@Aspect
class AopAdviceConfig {

    @Before("execution(* *.*(..))")
    public void beforeAdvice(JoinPoint joinPoint) {
        System.out.println(joinPoint.getTarget());
        System.out.println("前置通知....");
    }
}
//定義一個介面
interface AspectJService {

    //測試前置通知
    void beforeAdvice();
    //測試後置通知
    void afterAdvice();
}
//實現類
class AspectJServiceImpl implements AspectJService {

    @Override
    public void beforeAdvice() {
        System.out.println("測試前置通知,我是第一個Service。。。。。。");
    }

    //測試後置通知
    @Override
    public void afterAdvice() {
        System.out.println("測試AspectJ後置通知。。。。");
    }
}
public static void main(String[] args) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
//手工建立一個例項
        AspectJService aspectJService = new AspectJServiceImpl();
        //使用AspectJ語法 自動建立代理物件
        AspectJProxyFactory aspectJProxyFactory = new AspectJProxyFactory(aspectJService);
        //新增切面和通知類
        aspectJProxyFactory.addAspect(AopAdviceConfig.class);
        //建立代理物件
        AspectJService proxyService = aspectJProxyFactory.getProxy();
        //進行方法呼叫
        proxyService.beforeAdvice();
    }

AspectJProxyFactory aspectJProxyFactory = new AspectJProxyFactory(aspectJService)進行分析

[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片儲存下來直接上傳(img-eysZ7rqp-1624286179017)(C:\Users\Itcod\AppData\Roaming\Typora\typora-user-images\image-20210621093703583.png)]

public AspectJProxyFactory(Object target) {
		Assert.notNull(target, "Target object must not be null");
		setInterfaces(ClassUtils.getAllInterfaces(target));
		setTarget(target);
	}

// ClassUtils.$getAllInterfaces
// 獲取instance類的所有的介面,包括超類介面
public static Class<?>[] getAllInterfaces(Object instance) {
		Assert.notNull(instance, "Instance must not be null");
		return getAllInterfacesForClass(instance.getClass());
	}

public static Set<Class<?>> getAllInterfacesForClassAsSet(Class<?> clazz, @Nullable ClassLoader classLoader) {
		Assert.notNull(clazz, "Class must not be null");
    	// clazz: "class AspectJServiceImpl" 判斷是否可見、是否是介面
		if (clazz.isInterface() && isVisible(clazz, classLoader)) {
            // 如果是介面且可見的直接返回
			return Collections.singleton(clazz);
		}
		Set<Class<?>> interfaces = new LinkedHashSet<>();
    	// 根據當前介面進行向上搜尋,獲取所有的介面
		Class<?> current = clazz;
		while (current != null) {
			Class<?>[] ifcs = current.getInterfaces();
			for (Class<?> ifc : ifcs) {
				if (isVisible(ifc, classLoader)) {
					interfaces.add(ifc);
				}
			}
			current = current.getSuperclass();
		}
		return interfaces;
	}

// this.setInterfaces
public void setInterfaces(Class<?>... interfaces) {
		Assert.notNull(interfaces, "Interfaces must not be null");
    	// 清除原來介面資訊,interfaces是一個ArrayList物件
		this.interfaces.clear();
		for (Class<?> ifc : interfaces) {
			addInterface(ifc);
		}
	}
// 對target類包裝成SingletonTargetSource類
public void setTarget(Object target) {
		setTargetSource(new SingletonTargetSource(target));
	}
// SingletonTargetSource為TargetSource的子類
public void setTargetSource(@Nullable TargetSource targetSource) {
		this.targetSource = (targetSource != null ? targetSource : EMPTY_TARGET_SOURCE);
	}

新增切面類aspectJProxyFactory.addAspect(AopAdviceConfig.class);

這個方法主要呼叫了createAspectMetacdata、createAspectInstanceFactory、 addAdvisorsFromAspectInstanceFactory三個重要的方法

public void addAspect(Class<?> aspectClass) {
    	// 獲取aspectClass的非限定類名
		String aspectName = aspectClass.getName();
    	// 獲取Aspect的一個包裝類
		AspectMetadata am = createAspectMetadata(aspectClass, aspectName);
		MetadataAwareAspectInstanceFactory instanceFactory = createAspectInstanceFactory(am, aspectClass, aspectName);
		addAdvisorsFromAspectInstanceFactory(instanceFactory);
	}
private AspectMetadata createAspectMetadata(Class<?> aspectClass, String aspectName) {
    	// 將切面類和類名包裝到AspectMetadata
		AspectMetadata am = new AspectMetadata(aspectClass, aspectName);
		if (!am.getAjType().isAspect()) {
			throw new IllegalArgumentException("Class [" + aspectClass.getName() + "] is not a valid aspect type");
		}
		return am;
	}
public class AspectMetadata implements Serializable {
	private final String aspectName;
	private final Class<?> aspectClass;
    // 類的型別 這個是AspectJ中定義的類 儲存了aspectClass類的類相關資訊 實現類為 AjTypeImpl
	private transient AjType<?> ajType;
    // 切面表示式
	private final Pointcut perClausePointcut;
    
    public AspectMetadata(Class<?> aspectClass, String aspectName) {
		this.aspectName = aspectName;

		Class<?> currClass = aspectClass;
		AjType<?> ajType = null;
       	// 向上搜尋被@Aspect註解的類,直到Object
		while (currClass != Object.class) {
            // 原始碼解釋:這是 AspectJ 執行時型別系統的錨點,在執行時獲取給定型別的 AjType 表示的典型用法是呼叫
			AjType<?> ajTypeToCheck = AjTypeSystem.getAjType(currClass);
			if (ajTypeToCheck.isAspect()) {
				ajType = ajTypeToCheck;
				break;
			}
			currClass = currClass.getSuperclass();
		}
		if (ajType == null) {
			throw new IllegalArgumentException("Class '" + aspectClass.getName() + "' is not an @AspectJ aspect");
		}
		if (ajType.getDeclarePrecedence().length > 0) {
			throw new IllegalArgumentException("DeclarePrecedence not presently supported in Spring AOP");
		}
        // 被反向代理了,從包裝物件中獲取切面類
		this.aspectClass = ajType.getJavaClass();
        // 維護本代理的包裝物件
		this.ajType = ajType;

		switch (this.ajType.getPerClause().getKind()) {
			
		}
	}
}
/**
* Return the AspectJ runtime type representation of the given Java type.
* Unlike java.lang.Class, AjType understands pointcuts, advice, declare statements,
* and other AspectJ type members. AjType is the recommended reflection API for
* AspectJ programs as it offers everything that java.lang.reflect does, with 
* AspectJ-awareness on top.
*/
// 獲取所傳類的AjType
public static <T> AjType<T> getAjType(Class<T> fromClass) {
			WeakReference<AjType> weakRefToAjType =  ajTypes.get(fromClass);
			if (weakRefToAjType!=null) {
                // 從快取獲取包裝類AjType
				AjType<T> theAjType = weakRefToAjType.get();
				if (theAjType != null) {
					return theAjType;
				} else {
					theAjType = new AjTypeImpl<T>(fromClass);
					ajTypes.put(fromClass, new WeakReference<AjType>(theAjType));
					return theAjType;
				}
			}
			// neither key nor value was found
    		// 對fromClass包裝成AjType型別,同時進行快取
			AjType<T> theAjType =  new AjTypeImpl<T>(fromClass);
			ajTypes.put(fromClass, new WeakReference<AjType>(theAjType));
			return theAjType;
		}

createAspectInstanceFactory從名稱可以看出這個方法是建立切面例項的一個工廠方法

private MetadataAwareAspectInstanceFactory createAspectInstanceFactory(
			AspectMetadata am, Class<?> aspectClass, String aspectName) {

		MetadataAwareAspectInstanceFactory instanceFactory;
   		//是否是單例 
		if (am.getAjType().getPerClause().getKind() == PerClauseKind.SINGLETON) {
			// Create a shared aspect instance.
            // 根據切面類建立一個切面類例項 需要無參構造方法
			Object instance = getSingletonAspectInstance(aspectClass);
            // 將instance封裝到SingletonMetadataAwareAspectInstanceFactory中
            // 該類是一個單例的帶有切面元資料的切面工廠,內部再次封裝了一個AspectMetadata物件
			instanceFactory = new SingletonMetadataAwareAspectInstanceFactory(instance, aspectName);
		}
		else {
			// Create a factory for independent aspect instances.
            // 將切面類封裝到SimpleMetadataAwareAspectInstanceFactory中
            // 該類是一個單例的帶有切面元資料的切面工廠,內部也封裝了一個AspectMetadata物件
			instanceFactory = new SimpleMetadataAwareAspectInstanceFactory(aspectClass, aspectName);
		}
		return instanceFactory;
	}
private Object getSingletonAspectInstance(Class<?> aspectClass) {
		// Quick check without a lock...
    	// 先嚐試從快取中嘗試獲取例項
		Object instance = aspectCache.get(aspectClass);
		if (instance == null) {
            // 由於是單例設計,避免多執行緒的重複獲取,進行加鎖
			synchronized (aspectCache) {
				// To be safe, check within full lock now...
				instance = aspectCache.get(aspectClass);
				if (instance == null) {
					instance = new SimpleAspectInstanceFactory(aspectClass).getAspectInstance();
                    /*
                    public final Object getAspectInstance() {
                    	// 通過ReflectionUtils工具類獲取Class表示的物件
                    	return ReflectionUtils.accessibleConstructor(this.aspectClass).newInstance();
                    }
                    */
                    // 快取獲取的例項
					aspectCache.put(aspectClass, instance);
				}
			}
		}
		return instance;
	}

這個方法建立了一個MetaDataAwareAspectinstanceFactory的子類,用來組合切面例項和切面元資料。

addAdvisorsFromAspectInstanceFactory是一個重點的方法,獲取Advisor的邏輯都在裡面

private void addAdvisorsFromAspectInstanceFactory(MetadataAwareAspectInstanceFactory instanceFactory) {
    	// 獲取切面類,是一個帶有Aspect註解的類,不一定是addAspect傳入的類可能是其父類
		List<Advisor> advisors = this.aspectFactory.getAdvisors(instanceFactory);
    	// 目標類
		Class<?> targetClass = getTargetClass();
		Assert.state(targetClass != null, "Unresolvable target class");
		advisors = AopUtils.findAdvisorsThatCanApply(advisors, targetClass);
		AspectJProxyUtils.makeAdvisorChainAspectJCapableIfNecessary(advisors);
		AnnotationAwareOrderComparator.sort(advisors);
		addAdvisors(advisors);
	}

先看下getAdvisors實現

public List<Advisor> getAdvisors(MetadataAwareAspectInstanceFactory aspectInstanceFactory) {
    	// 從aspectInstanceFactory中獲取上一步快取在其中的資料
		Class<?> aspectClass = aspectInstanceFactory.getAspectMetadata().getAspectClass();
		String aspectName = aspectInstanceFactory.getAspectMetadata().getAspectName();
    	// 驗證aspectClass例項
		validate(aspectClass);

		// We need to wrap the MetadataAwareAspectInstanceFactory with a decorator
		// so that it will only instantiate once.
        //將上一步獲取的MetadataAwareAspectInstanceFactory例項又包裝為LazySingletonAspectInstanceFactoryDecorator
        //裝飾模式的一個使用
        //確保只獲取到一個切面例項
		MetadataAwareAspectInstanceFactory lazySingletonAspectInstanceFactory =
				new LazySingletonAspectInstanceFactoryDecorator(aspectInstanceFactory);

		List<Advisor> advisors = new ArrayList<>();
    	// 獲取切面物件中所有的響應方法(advisor)包括父類中的
		for (Method method : getAdvisorMethods(aspectClass)) {
			// Prior to Spring Framework 5.2.7, advisors.size() was supplied as the declarationOrderInAspect
			// to getAdvisor(...) to represent the "current position" in the declared methods list.
			// However, since Java 7 the "current position" is not valid since the JDK no longer
			// returns declared methods in the order in which they are declared in the source code.
			// Thus, we now hard code the declarationOrderInAspect to 0 for all advice methods
			// discovered via reflection in order to support reliable advice ordering across JVM launches.
			// Specifically, a value of 0 aligns with the default value used in
			// AspectJPrecedenceComparator.getAspectDeclarationOrder(Advisor).
			Advisor advisor = getAdvisor(method, lazySingletonAspectInstanceFactory, 0, aspectName);
			if (advisor != null) {
				advisors.add(advisor);
			}
		}

		// If it's a per target aspect, emit the dummy instantiating aspect.
		if (!advisors.isEmpty() && lazySingletonAspectInstanceFactory.getAspectMetadata().isLazilyInstantiated()) {
			Advisor instantiationAdvisor = new SyntheticInstantiationAdvisor(lazySingletonAspectInstanceFactory);
			advisors.add(0, instantiationAdvisor);
		}

		// Find introduction fields.
    	// 獲取切面類中的屬性
		for (Field field : aspectClass.getDeclaredFields()) {
			Advisor advisor = getDeclareParentsAdvisor(field);
			if (advisor != null) {
				advisors.add(advisor);
			}
		}

		return advisors;
	}
public Advisor getAdvisor(Method candidateAdviceMethod, MetadataAwareAspectInstanceFactory aspectInstanceFactory,
			int declarationOrderInAspect, String aspectName) {

		validate(aspectInstanceFactory.getAspectMetadata().getAspectClass());
		// 獲取切面類的切點方法的表示式例項
		AspectJExpressionPointcut expressionPointcut = getPointcut(
				candidateAdviceMethod, aspectInstanceFactory.getAspectMetadata().getAspectClass());
		if (expressionPointcut == null) {
			return null;
		}
		// 對錶達式例項,切點、aspectAdvisorFactory、切面例項工廠、、切面名進行統一包裝
		return new InstantiationModelAwarePointcutAdvisorImpl(expressionPointcut, candidateAdviceMethod,
				this, aspectInstanceFactory, declarationOrderInAspect, aspectName);
	}

[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片儲存下來直接上傳(img-L1S8JKqr-1624286179018)(C:\Users\Itcod\AppData\Roaming\Typora\typora-user-images\image-20210621222207939.png)]

可以看出InstantiationModelAwarePointcutAdvisorImpl是InstantiationModelAwarePointcutAdvisor的實現類同時是Advisor的一個子類。

@Nullable
	private AspectJExpressionPointcut getPointcut(Method candidateAdviceMethod, Class<?> candidateAspectClass) {
		AspectJAnnotation<?> aspectJAnnotation =
				AbstractAspectJAdvisorFactory.findAspectJAnnotationOnMethod(candidateAdviceMethod);
        /*
        protected static AspectJAnnotation<?> findAspectJAnnotationOnMethod(Method method) {
        	// 檢視響應方法是被哪個註解類註解的
        	// ASPECTJ_ANNOTATION_CLASSES = 
			Pointcut.class, Around.class, Before.class, After.class, AfterReturning.class, AfterThrowing.class
			
            for (Class<?> clazz : ASPECTJ_ANNOTATION_CLASSES) {
                AspectJAnnotation<?> foundAnnotation = findAnnotation(method, (Class<Annotation>) clazz);
                if (foundAnnotation != null) {
                    return foundAnnotation;
                }
            }
            return null;
        }
        */
		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;
	}

可以看出在已經分析的這兩個方法中,對Aop的切面進行了驗證和向上搜尋可能包含的切面類、獲取了切面類中全部的切點方法,已經對切點方法的表示式進行了包裝儲存在AspectJProxyFactory的物件裡(粗淺概括)