浅析: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代理的创建