[spring6: AspectJAdvisorFactory AspectJProxyFactory]-源码解析
推荐阅读:
- [spring6: AspectMetadata & AspectInstanceFactory]-源码解析
- [spring6: TargetSource & AopProxyFactory & AdvisorChainFactory & ProxyFactory]-源码分析
AspectJAdvisorFactory
AspectJAdvisorFactory
接口用于从使用 AspectJ 注解语法的类中创建 Spring AOP Advisor
public interface AspectJAdvisorFactory {boolean isAspect(Class<?> clazz);void validate(Class<?> aspectClass) throws AopConfigException;List<Advisor> getAdvisors(MetadataAwareAspectInstanceFactory aspectInstanceFactory);@NullableAdvisor getAdvisor(Method candidateAdviceMethod, MetadataAwareAspectInstanceFactory aspectInstanceFactory,int declarationOrder, String aspectName);@NullableAdvice getAdvice(Method candidateAdviceMethod, AspectJExpressionPointcut expressionPointcut,MetadataAwareAspectInstanceFactory aspectInstanceFactory, int declarationOrder, String aspectName);}
ReflectiveAspectJAdvisorFactory
ReflectiveAspectJAdvisorFactory
负责通过反射从AspectJ注解方法创建Spring AOP的Advisor,并管理切面方法的生命周期与排序。
public class ReflectiveAspectJAdvisorFactory extends AbstractAspectJAdvisorFactory implements Serializable {// Exclude @Pointcut methodsprivate static final MethodFilter adviceMethodFilter = ReflectionUtils.USER_DECLARED_METHODS.and(method -> (AnnotationUtils.getAnnotation(method, Pointcut.class) == null));private static final Comparator<Method> adviceMethodComparator;static {// 注:// 尽管`@After`的顺序排在`@AfterReturning`和`@AfterThrowing`之前,// 但实际上`@After`通知方法会在`@AfterReturning`和`@AfterThrowing`方法之后被调用,// 这是因为`AspectJAfterAdvice.invoke(MethodInvocation)`在`try`块中调用`proceed()`,// 并且只在相应的`finally`块中调用`@After`通知方法。Comparator<Method> adviceKindComparator = new ConvertingComparator<>(new InstanceComparator<>(Around.class, Before.class, After.class, AfterReturning.class, AfterThrowing.class),(Converter<Method, Annotation>) method -> {AspectJAnnotation ann = AbstractAspectJAdvisorFactory.findAspectJAnnotationOnMethod(method);return (ann != null ? ann.getAnnotation() : null);});Comparator<Method> methodNameComparator = new ConvertingComparator<>(Method::getName);adviceMethodComparator = adviceKindComparator.thenComparing(methodNameComparator);}@Nullableprivate final BeanFactory beanFactory;public ReflectiveAspectJAdvisorFactory() {this(null);}public ReflectiveAspectJAdvisorFactory(@Nullable BeanFactory beanFactory) {this.beanFactory = beanFactory;}@Overridepublic List<Advisor> getAdvisors(MetadataAwareAspectInstanceFactory aspectInstanceFactory) {Class<?> aspectClass = aspectInstanceFactory.getAspectMetadata().getAspectClass();String aspectName = aspectInstanceFactory.getAspectMetadata().getAspectName();validate(aspectClass);// 我们需要将MetadataAwareAspectInstanceFactory包装成一个装饰器,以确保它只会被实例化一次MetadataAwareAspectInstanceFactory lazySingletonAspectInstanceFactory =new LazySingletonAspectInstanceFactoryDecorator(aspectInstanceFactory);List<Advisor> advisors = new ArrayList<>();for (Method method : getAdvisorMethods(aspectClass)) {if (method.equals(ClassUtils.getMostSpecificMethod(method, aspectClass))) {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;}private List<Method> getAdvisorMethods(Class<?> aspectClass) {List<Method> methods = new ArrayList<>();ReflectionUtils.doWithMethods(aspectClass, methods::add, adviceMethodFilter);if (methods.size() > 1) {methods.sort(adviceMethodComparator);}return methods;}// 通过反射检查字段是否具有 @DeclareParents 注解,// 并根据注解的内容构建一个 DeclareParentsAdvisor@Nullableprivate Advisor getDeclareParentsAdvisor(Field introductionField) {DeclareParents declareParents = introductionField.getAnnotation(DeclareParents.class);if (declareParents == null) {// Not an introduction fieldreturn null;}if (DeclareParents.class == declareParents.defaultImpl()) {throw new IllegalStateException("'defaultImpl' attribute must be set on DeclareParents");}return new DeclareParentsAdvisor(introductionField.getType(), declareParents.value(), declareParents.defaultImpl());}// 为给定的建议方法(candidateAdviceMethod)创建一个 Advisor,并通过 Pointcut 来确定其切入点。它还考虑了异常处理和日志记录@Override@Nullablepublic 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;}try {return new InstantiationModelAwarePointcutAdvisorImpl(expressionPointcut, candidateAdviceMethod,this, aspectInstanceFactory, declarationOrderInAspect, aspectName);}catch (IllegalArgumentException | IllegalStateException ex) {if (logger.isDebugEnabled()) {logger.debug("Ignoring incompatible advice method: " + candidateAdviceMethod, ex);}return null;}}// 为给定的 candidateAdviceMethod 方法和 candidateAspectClass 类创建一个 AspectJExpressionPointcut,并配置相关的表达式和 BeanFactory,如果存在的话。@Nullableprivate AspectJExpressionPointcut getPointcut(Method candidateAdviceMethod, Class<?> candidateAspectClass) {AspectJAnnotation aspectJAnnotation =AbstractAspectJAdvisorFactory.findAspectJAnnotationOnMethod(candidateAdviceMethod);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;}// 根据方法上使用的 AspectJ 注解类型(@Around、@Before、@After 等),创建并配置相应的 Advice 对象。// 不同的通知类型会创建不同的 Advice 实现类,并配置相关参数(如参数名称、顺序等)。// 最终返回一个准备好的 Advice,以供 AOP 机制在运行时使用。@Override@Nullablepublic Advice getAdvice(Method candidateAdviceMethod, AspectJExpressionPointcut expressionPointcut,MetadataAwareAspectInstanceFactory aspectInstanceFactory, int declarationOrder, String aspectName) {Class<?> candidateAspectClass = aspectInstanceFactory.getAspectMetadata().getAspectClass();validate(candidateAspectClass);AspectJAnnotation aspectJAnnotation =AbstractAspectJAdvisorFactory.findAspectJAnnotationOnMethod(candidateAdviceMethod);if (aspectJAnnotation == null) {return null;}// If we get here, we know we have an AspectJ method.// Check that it's an AspectJ-annotated classif (!isAspect(candidateAspectClass)) {throw new AopConfigException("Advice must be declared inside an aspect type: " +"Offending method '" + candidateAdviceMethod + "' in class [" +candidateAspectClass.getName() + "]");}if (logger.isDebugEnabled()) {logger.debug("Found AspectJ method: " + candidateAdviceMethod);}AbstractAspectJAdvice springAdvice;switch (aspectJAnnotation.getAnnotationType()) {case AtPointcut -> {if (logger.isDebugEnabled()) {logger.debug("Processing pointcut '" + candidateAdviceMethod.getName() + "'");}return null;}case AtAround -> springAdvice = new AspectJAroundAdvice(candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);case AtBefore -> springAdvice = new AspectJMethodBeforeAdvice(candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);case AtAfter -> springAdvice = new AspectJAfterAdvice(candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);case AtAfterReturning -> {springAdvice = new AspectJAfterReturningAdvice(candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);AfterReturning afterReturningAnnotation = (AfterReturning) aspectJAnnotation.getAnnotation();if (StringUtils.hasText(afterReturningAnnotation.returning())) {springAdvice.setReturningName(afterReturningAnnotation.returning());}}case AtAfterThrowing -> {springAdvice = new AspectJAfterThrowingAdvice(candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);AfterThrowing afterThrowingAnnotation = (AfterThrowing) aspectJAnnotation.getAnnotation();if (StringUtils.hasText(afterThrowingAnnotation.throwing())) {springAdvice.setThrowingName(afterThrowingAnnotation.throwing());}}default -> throw new UnsupportedOperationException("Unsupported advice type on method: " + candidateAdviceMethod);}// Now to configure the advice...springAdvice.setAspectName(aspectName);springAdvice.setDeclarationOrder(declarationOrder);String[] argNames = this.parameterNameDiscoverer.getParameterNames(candidateAdviceMethod);if (argNames != null) {springAdvice.setArgumentNamesFromStringArray(argNames);}springAdvice.calculateArgumentBindings();return springAdvice;}// SyntheticInstantiationAdvisor 是一个伪造的 Advisor,主要用于通过 per-clause pointcut 来触发非单例切面的实例化。// 每次切点匹配时,会通过 MethodBeforeAdvice 创建切面实例,但没有附加其他行为,因此它不会影响方法的执行。@SuppressWarnings("serial")protected static class SyntheticInstantiationAdvisor extends DefaultPointcutAdvisor {public SyntheticInstantiationAdvisor(final MetadataAwareAspectInstanceFactory aif) {super(aif.getAspectMetadata().getPerClausePointcut(), (MethodBeforeAdvice)(method, args, target) -> aif.getAspectInstance());}}}
AspectJProxyFactory
AspectJProxyFactory
是一个用于构建 AspectJ 代理的工厂类,可以通过它为目标对象添加 AspectJ 切面,并自动创建代理。 通过 addAspect 方法,可以将指定的切面(单例或非单例)添加到代理中,然后通过 getProxy 方法生成包含切面的代理对象。该类支持单例切面的处理和为非单例切面创建实例工厂。通过这种方式,可以灵活地将切面逻辑应用到目标对象的不同方法中,支持 AOP 编程模型。
@SuppressWarnings("serial")
public class AspectJProxyFactory extends ProxyCreatorSupport {/** Cache for singleton aspect instances. */private static final Map<Class<?>, Object> aspectCache = new ConcurrentHashMap<>();private final AspectJAdvisorFactory aspectFactory = new ReflectiveAspectJAdvisorFactory();public AspectJProxyFactory() {}public AspectJProxyFactory(Object target) {Assert.notNull(target, "Target object must not be null");setInterfaces(ClassUtils.getAllInterfaces(target));setTarget(target);}public AspectJProxyFactory(Class<?>... interfaces) {setInterfaces(interfaces);}public void addAspect(Object aspectInstance) {Class<?> aspectClass = aspectInstance.getClass();String aspectName = aspectClass.getName();AspectMetadata am = createAspectMetadata(aspectClass, aspectName);if (am.getAjType().getPerClause().getKind() != PerClauseKind.SINGLETON) {throw new IllegalArgumentException("Aspect class [" + aspectClass.getName() + "] does not define a singleton aspect");}addAdvisorsFromAspectInstanceFactory(new SingletonMetadataAwareAspectInstanceFactory(aspectInstance, aspectName));}public void addAspect(Class<?> aspectClass) {String aspectName = aspectClass.getName();AspectMetadata am = createAspectMetadata(aspectClass, aspectName);MetadataAwareAspectInstanceFactory instanceFactory = createAspectInstanceFactory(am, aspectClass, aspectName);addAdvisorsFromAspectInstanceFactory(instanceFactory);}private void addAdvisorsFromAspectInstanceFactory(MetadataAwareAspectInstanceFactory instanceFactory) {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);}private AspectMetadata createAspectMetadata(Class<?> aspectClass, String aspectName) {AspectMetadata am = new AspectMetadata(aspectClass, aspectName);if (!am.getAjType().isAspect()) {throw new IllegalArgumentException("Class [" + aspectClass.getName() + "] is not a valid aspect type");}return am;}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);instanceFactory = new SingletonMetadataAwareAspectInstanceFactory(instance, aspectName);}else {// Create a factory for independent aspect instances.instanceFactory = new SimpleMetadataAwareAspectInstanceFactory(aspectClass, aspectName);}return instanceFactory;}private Object getSingletonAspectInstance(Class<?> aspectClass) {return aspectCache.computeIfAbsent(aspectClass,clazz -> new SimpleAspectInstanceFactory(clazz).getAspectInstance());}@SuppressWarnings("unchecked")public <T> T getProxy() {return (T) createAopProxy().getProxy();}@SuppressWarnings("unchecked")public <T> T getProxy(ClassLoader classLoader) {return (T) createAopProxy().getProxy(classLoader);}}