Skip to content

Spring AOP does not propagate arguments for dynamic prototype-scoped advice  #28407

Closed
@ZhongGuoDragon

Description

@ZhongGuoDragon

If we use prototype aspect expression, and we need args type is String, but we can input other type class,the aspect method is work.

code like this:

@Aspect("perthis(execution(* com.tom.test.demo..*(..)))")
@Component
@Scope(value = "prototype")
//@Aspect("")
//@Component
////@Scope(value = "prototype")
public class AspectJ2 {
    private int num = 0;

    @Before("execution(* com.tom.test.demo..*(..)) && args(java.lang.String)")
    public <T extends String> void pointCut(JoinPoint joinPoint) {
        System.out.println("????????????????????????");
        for (int i = 0; i < joinPoint.getArgs().length; i++) {
            System.out.println(joinPoint.getArgs()[i].getClass());
            System.out.println(joinPoint.getArgs()[i]);
        }
        System.out.println("????????????????????????");
    }
}
package com.tom.test.demo;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;

import java.util.ArrayList;
import java.util.List;

@Component()
public class Child extends Father{

    public String  setStrings(Object object) {
        return "sssss";
    }
}
Child second = (Child) context.getBean("child");
second.setStrings("abcdefg");
second.setStrings(11111111);

the console will output:

????????????????????????
class java.lang.String
abcdefg
????????????????????????
????????????????????????
class java.lang.Integer
11111111
????????????????????????

I see the code:

package org.springframework.aop.aspectj.annotation;

public InstantiationModelAwarePointcutAdvisorImpl(AspectJExpressionPointcut declaredPointcut,
			Method aspectJAdviceMethod, AspectJAdvisorFactory aspectJAdvisorFactory,
			MetadataAwareAspectInstanceFactory aspectInstanceFactory, int declarationOrder, String aspectName) {

		this.declaredPointcut = declaredPointcut;
		this.declaringClass = aspectJAdviceMethod.getDeclaringClass();
		this.methodName = aspectJAdviceMethod.getName();
		this.parameterTypes = aspectJAdviceMethod.getParameterTypes();
		this.aspectJAdviceMethod = aspectJAdviceMethod;
		this.aspectJAdvisorFactory = aspectJAdvisorFactory;
		this.aspectInstanceFactory = aspectInstanceFactory;
		this.declarationOrder = declarationOrder;
		this.aspectName = aspectName;

		if (aspectInstanceFactory.getAspectMetadata().isLazilyInstantiated()) {
			// Static part of the pointcut is a lazy type.
			Pointcut preInstantiationPointcut = Pointcuts.union(
					aspectInstanceFactory.getAspectMetadata().getPerClausePointcut(), this.declaredPointcut);

			// Make it dynamic: must mutate from pre-instantiation to post-instantiation state.
			// If it's not a dynamic pointcut, it may be optimized out
			// by the Spring AOP infrastructure after the first evaluation.
			this.pointcut = new PerTargetInstantiationModelPointcut(
					this.declaredPointcut, preInstantiationPointcut, aspectInstanceFactory);
			this.lazy = true;
		}
		else {
			// A singleton aspect.
			this.pointcut = this.declaredPointcut;
			this.lazy = false;
			this.instantiatedAdvice = instantiateAdvice(this.declaredPointcut);
		}
	}
}

this kind AspectJ will obtain PerTargetInstantiationModelPointcut and its dynamic-match method is

boolean matches(Method method, Class<?> targetClass)

not

boolean matches(Method method, Class<?> targetClass, Object... args)

so, it lost dynamic judge, so we can pass the AspectJ with a Integer or Other args, because it only calculates static-match method, the Child.setStrings(Object object) will pass any object.

private static final class PerTargetInstantiationModelPointcut extends DynamicMethodMatcherPointcut {

		@Override
		public boolean matches(Method method, Class<?> targetClass, Object... args) {
			// you can see this.declaredPointcut.matches(method, targetClass)) is not dynamic
			return (isAspectMaterialized() && this.declaredPointcut.matches(method, targetClass));
		}

}

Metadata

Metadata

Assignees

Labels

in: coreIssues in core modules (aop, beans, core, context, expression)status: backportedAn issue that has been backported to maintenance branchestype: bugA general bug

Type

No type

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions