Skip ajc-compiled aspects for ajc-compiled target classes
Includes defensive ignoring of incompatible aspect types. Closes gh-32970
This commit is contained in:
parent
c28a0d5627
commit
0ea96b4806
|
|
@ -18,6 +18,7 @@ package org.springframework.aop.aspectj;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.ObjectInputStream;
|
import java.io.ObjectInputStream;
|
||||||
|
import java.lang.reflect.Field;
|
||||||
import java.lang.reflect.Method;
|
import java.lang.reflect.Method;
|
||||||
import java.lang.reflect.Proxy;
|
import java.lang.reflect.Proxy;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
|
@ -86,6 +87,8 @@ import org.springframework.util.StringUtils;
|
||||||
public class AspectJExpressionPointcut extends AbstractExpressionPointcut
|
public class AspectJExpressionPointcut extends AbstractExpressionPointcut
|
||||||
implements ClassFilter, IntroductionAwareMethodMatcher, BeanFactoryAware {
|
implements ClassFilter, IntroductionAwareMethodMatcher, BeanFactoryAware {
|
||||||
|
|
||||||
|
private static final String AJC_MAGIC = "ajc$";
|
||||||
|
|
||||||
private static final Set<PointcutPrimitive> SUPPORTED_PRIMITIVES = Set.of(
|
private static final Set<PointcutPrimitive> SUPPORTED_PRIMITIVES = Set.of(
|
||||||
PointcutPrimitive.EXECUTION,
|
PointcutPrimitive.EXECUTION,
|
||||||
PointcutPrimitive.ARGS,
|
PointcutPrimitive.ARGS,
|
||||||
|
|
@ -103,6 +106,8 @@ public class AspectJExpressionPointcut extends AbstractExpressionPointcut
|
||||||
@Nullable
|
@Nullable
|
||||||
private Class<?> pointcutDeclarationScope;
|
private Class<?> pointcutDeclarationScope;
|
||||||
|
|
||||||
|
private boolean aspectCompiledByAjc;
|
||||||
|
|
||||||
private String[] pointcutParameterNames = new String[0];
|
private String[] pointcutParameterNames = new String[0];
|
||||||
|
|
||||||
private Class<?>[] pointcutParameterTypes = new Class<?>[0];
|
private Class<?>[] pointcutParameterTypes = new Class<?>[0];
|
||||||
|
|
@ -134,7 +139,7 @@ public class AspectJExpressionPointcut extends AbstractExpressionPointcut
|
||||||
* @param paramTypes the parameter types for the pointcut
|
* @param paramTypes the parameter types for the pointcut
|
||||||
*/
|
*/
|
||||||
public AspectJExpressionPointcut(Class<?> declarationScope, String[] paramNames, Class<?>[] paramTypes) {
|
public AspectJExpressionPointcut(Class<?> declarationScope, String[] paramNames, Class<?>[] paramTypes) {
|
||||||
this.pointcutDeclarationScope = declarationScope;
|
setPointcutDeclarationScope(declarationScope);
|
||||||
if (paramNames.length != paramTypes.length) {
|
if (paramNames.length != paramTypes.length) {
|
||||||
throw new IllegalStateException(
|
throw new IllegalStateException(
|
||||||
"Number of pointcut parameter names must match number of pointcut parameter types");
|
"Number of pointcut parameter names must match number of pointcut parameter types");
|
||||||
|
|
@ -149,6 +154,7 @@ public class AspectJExpressionPointcut extends AbstractExpressionPointcut
|
||||||
*/
|
*/
|
||||||
public void setPointcutDeclarationScope(Class<?> pointcutDeclarationScope) {
|
public void setPointcutDeclarationScope(Class<?> pointcutDeclarationScope) {
|
||||||
this.pointcutDeclarationScope = pointcutDeclarationScope;
|
this.pointcutDeclarationScope = pointcutDeclarationScope;
|
||||||
|
this.aspectCompiledByAjc = compiledByAjc(pointcutDeclarationScope);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -274,6 +280,11 @@ public class AspectJExpressionPointcut extends AbstractExpressionPointcut
|
||||||
@Override
|
@Override
|
||||||
public boolean matches(Class<?> targetClass) {
|
public boolean matches(Class<?> targetClass) {
|
||||||
if (this.pointcutParsingFailed) {
|
if (this.pointcutParsingFailed) {
|
||||||
|
// Pointcut parsing failed before below -> avoid trying again.
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (this.aspectCompiledByAjc && compiledByAjc(targetClass)) {
|
||||||
|
// ajc-compiled aspect class for ajc-compiled target class -> already weaved.
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -536,6 +547,15 @@ public class AspectJExpressionPointcut extends AbstractExpressionPointcut
|
||||||
return resolveExpression().contains("@annotation");
|
return resolveExpression().contains("@annotation");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static boolean compiledByAjc(Class<?> clazz) {
|
||||||
|
for (Field field : clazz.getDeclaredFields()) {
|
||||||
|
if (field.getName().startsWith(AJC_MAGIC)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean equals(@Nullable Object other) {
|
public boolean equals(@Nullable Object other) {
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2002-2020 the original author or authors.
|
* Copyright 2002-2024 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
|
@ -22,9 +22,12 @@ import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
|
||||||
|
import org.apache.commons.logging.Log;
|
||||||
|
import org.apache.commons.logging.LogFactory;
|
||||||
import org.aspectj.lang.reflect.PerClauseKind;
|
import org.aspectj.lang.reflect.PerClauseKind;
|
||||||
|
|
||||||
import org.springframework.aop.Advisor;
|
import org.springframework.aop.Advisor;
|
||||||
|
import org.springframework.aop.framework.AopConfigException;
|
||||||
import org.springframework.beans.factory.BeanFactoryUtils;
|
import org.springframework.beans.factory.BeanFactoryUtils;
|
||||||
import org.springframework.beans.factory.ListableBeanFactory;
|
import org.springframework.beans.factory.ListableBeanFactory;
|
||||||
import org.springframework.lang.Nullable;
|
import org.springframework.lang.Nullable;
|
||||||
|
|
@ -40,6 +43,8 @@ import org.springframework.util.Assert;
|
||||||
*/
|
*/
|
||||||
public class BeanFactoryAspectJAdvisorsBuilder {
|
public class BeanFactoryAspectJAdvisorsBuilder {
|
||||||
|
|
||||||
|
private static final Log logger = LogFactory.getLog(BeanFactoryAspectJAdvisorsBuilder.class);
|
||||||
|
|
||||||
private final ListableBeanFactory beanFactory;
|
private final ListableBeanFactory beanFactory;
|
||||||
|
|
||||||
private final AspectJAdvisorFactory advisorFactory;
|
private final AspectJAdvisorFactory advisorFactory;
|
||||||
|
|
@ -102,30 +107,37 @@ public class BeanFactoryAspectJAdvisorsBuilder {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (this.advisorFactory.isAspect(beanType)) {
|
if (this.advisorFactory.isAspect(beanType)) {
|
||||||
aspectNames.add(beanName);
|
try {
|
||||||
AspectMetadata amd = new AspectMetadata(beanType, beanName);
|
AspectMetadata amd = new AspectMetadata(beanType, beanName);
|
||||||
if (amd.getAjType().getPerClause().getKind() == PerClauseKind.SINGLETON) {
|
if (amd.getAjType().getPerClause().getKind() == PerClauseKind.SINGLETON) {
|
||||||
MetadataAwareAspectInstanceFactory factory =
|
MetadataAwareAspectInstanceFactory factory =
|
||||||
new BeanFactoryAspectInstanceFactory(this.beanFactory, beanName);
|
new BeanFactoryAspectInstanceFactory(this.beanFactory, beanName);
|
||||||
List<Advisor> classAdvisors = this.advisorFactory.getAdvisors(factory);
|
List<Advisor> classAdvisors = this.advisorFactory.getAdvisors(factory);
|
||||||
if (this.beanFactory.isSingleton(beanName)) {
|
if (this.beanFactory.isSingleton(beanName)) {
|
||||||
this.advisorsCache.put(beanName, classAdvisors);
|
this.advisorsCache.put(beanName, classAdvisors);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
this.aspectFactoryCache.put(beanName, factory);
|
||||||
|
}
|
||||||
|
advisors.addAll(classAdvisors);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
// Per target or per this.
|
||||||
|
if (this.beanFactory.isSingleton(beanName)) {
|
||||||
|
throw new IllegalArgumentException("Bean with name '" + beanName +
|
||||||
|
"' is a singleton, but aspect instantiation model is not singleton");
|
||||||
|
}
|
||||||
|
MetadataAwareAspectInstanceFactory factory =
|
||||||
|
new PrototypeAspectInstanceFactory(this.beanFactory, beanName);
|
||||||
this.aspectFactoryCache.put(beanName, factory);
|
this.aspectFactoryCache.put(beanName, factory);
|
||||||
|
advisors.addAll(this.advisorFactory.getAdvisors(factory));
|
||||||
}
|
}
|
||||||
advisors.addAll(classAdvisors);
|
aspectNames.add(beanName);
|
||||||
}
|
}
|
||||||
else {
|
catch (IllegalArgumentException | IllegalStateException | AopConfigException ex) {
|
||||||
// Per target or per this.
|
if (logger.isDebugEnabled()) {
|
||||||
if (this.beanFactory.isSingleton(beanName)) {
|
logger.debug("Ignoring incompatible aspect [" + beanType.getName() + "]: " + ex);
|
||||||
throw new IllegalArgumentException("Bean with name '" + beanName +
|
|
||||||
"' is a singleton, but aspect instantiation model is not singleton");
|
|
||||||
}
|
}
|
||||||
MetadataAwareAspectInstanceFactory factory =
|
|
||||||
new PrototypeAspectInstanceFactory(this.beanFactory, beanName);
|
|
||||||
this.aspectFactoryCache.put(beanName, factory);
|
|
||||||
advisors.addAll(this.advisorFactory.getAdvisors(factory));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -21,8 +21,10 @@
|
||||||
<property name="foo" value="bar"/>
|
<property name="foo" value="bar"/>
|
||||||
</bean>
|
</bean>
|
||||||
|
|
||||||
<bean id="otherBean" class="java.lang.Object"/>
|
<bean id="otherBean" class="org.springframework.beans.factory.aspectj.ShouldBeConfiguredBySpring"/>
|
||||||
|
|
||||||
<bean id="yetAnotherBean" class="java.lang.Object"/>
|
<bean id="yetAnotherBean" class="org.springframework.beans.factory.aspectj.ShouldBeConfiguredBySpring"/>
|
||||||
|
|
||||||
|
<bean id="configuredBean" class="org.springframework.beans.factory.aspectj.ShouldBeConfiguredBySpring" lazy-init="true"/>
|
||||||
|
|
||||||
</beans>
|
</beans>
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue