浅析:AOP的advice和advisor创建过程

Posted 只有那些躺在坑里从不仰望高空的人,才不会再掉进坑里

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了浅析: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的对象里(粗浅概括)

以上是关于浅析:AOP的advice和advisor创建过程的主要内容,如果未能解决你的问题,请参考以下文章

Spring笔记07(Spring AOP的通知advice和顾问advisor)

Spring框架系列(10) - Spring AOP实现原理详解之AOP代理的创建

spring AOP 概述 Advisor

Spring系列之AOP分析之代理对象的创建

011-Spring aop 002-核心说明-切点PointCut通知Advice切面Advisor

Spring 注解--AOP篇