Description
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));
}
}