推荐阅读:
AspectJAdvisorFactory
接口用于从使用 AspectJ 注解语法的类中创建 Spring AOP Advisor
public interface AspectJAdvisorFactory {
boolean isAspect(Class<?> clazz);
void validate(Class<?> aspectClass) throws AopConfigException;
List<Advisor> getAdvisors(MetadataAwareAspectInstanceFactory aspectInstanceFactory);
@Nullable
Advisor getAdvisor(Method candidateAdviceMethod, MetadataAwareAspectInstanceFactory aspectInstanceFactory,
int declarationOrder, String aspectName);
@Nullable
Advice getAdvice(Method candidateAdviceMethod, AspectJExpressionPointcut expressionPointcut,
MetadataAwareAspectInstanceFactory aspectInstanceFactory, int declarationOrder, String aspectName);
}
ReflectiveAspectJAdvisorFactory
负责通过反射从AspectJ注解方法创建Spring AOP的Advisor,并管理切面方法的生命周期与排序。
public class ReflectiveAspectJAdvisorFactory extends AbstractAspectJAdvisorFactory implements Serializable {
// Exclude @Pointcut methods
private 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);
}
@Nullable
private final BeanFactory beanFactory;
public ReflectiveAspectJAdvisorFactory() {
this(null);
}
public ReflectiveAspectJAdvisorFactory(@Nullable BeanFactory beanFactory) {
this.beanFactory = beanFactory;
}
@Override
public 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
@Nullable
private Advisor getDeclareParentsAdvisor(Field introductionField) {
DeclareParents declareParents = introductionField.getAnnotation(DeclareParents.class);
if (declareParents == null) {
// Not an introduction field
return 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
@Nullable
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;
}
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,如果存在的话。
@Nullable
private 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
@Nullable
public 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 class
if (!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
是一个用于构建 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);
}
}