Skip to content

Commit

Permalink
Merge branch '6.1.x'
Browse files Browse the repository at this point in the history
# Conflicts:
#	spring-aop/src/main/java/org/springframework/aop/aspectj/AspectJExpressionPointcut.java
  • Loading branch information
jhoeller committed Jun 6, 2024
2 parents 7b9cbd7 + 2451bd6 commit 2aabe23
Show file tree
Hide file tree
Showing 7 changed files with 79 additions and 43 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@

package org.springframework.aop.aspectj;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.Arrays;
Expand Down Expand Up @@ -82,6 +83,8 @@
public class AspectJExpressionPointcut extends AbstractExpressionPointcut
implements ClassFilter, IntroductionAwareMethodMatcher, BeanFactoryAware {

private static final String AJC_MAGIC = "ajc$";

private static final Set<PointcutPrimitive> SUPPORTED_PRIMITIVES = Set.of(
PointcutPrimitive.EXECUTION,
PointcutPrimitive.ARGS,
Expand All @@ -99,6 +102,8 @@ public class AspectJExpressionPointcut extends AbstractExpressionPointcut
@Nullable
private Class<?> pointcutDeclarationScope;

private boolean aspectCompiledByAjc;

private String[] pointcutParameterNames = new String[0];

private Class<?>[] pointcutParameterTypes = new Class<?>[0];
Expand Down Expand Up @@ -128,7 +133,7 @@ public AspectJExpressionPointcut() {
* @param paramTypes the parameter types for the pointcut
*/
public AspectJExpressionPointcut(Class<?> declarationScope, String[] paramNames, Class<?>[] paramTypes) {
this.pointcutDeclarationScope = declarationScope;
setPointcutDeclarationScope(declarationScope);
if (paramNames.length != paramTypes.length) {
throw new IllegalStateException(
"Number of pointcut parameter names must match number of pointcut parameter types");
Expand All @@ -143,6 +148,7 @@ public AspectJExpressionPointcut(Class<?> declarationScope, String[] paramNames,
*/
public void setPointcutDeclarationScope(Class<?> pointcutDeclarationScope) {
this.pointcutDeclarationScope = pointcutDeclarationScope;
this.aspectCompiledByAjc = compiledByAjc(pointcutDeclarationScope);
}

/**
Expand Down Expand Up @@ -268,6 +274,11 @@ public PointcutExpression getPointcutExpression() {
@Override
public boolean matches(Class<?> targetClass) {
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;
}

Expand Down Expand Up @@ -523,6 +534,15 @@ private boolean containsAnnotationPointcut() {
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
public boolean equals(@Nullable Object other) {
Expand Down
Original file line number Diff line number Diff line change
@@ -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");
* you may not use this file except in compliance with the License.
Expand All @@ -22,9 +22,12 @@
import java.util.Map;
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.springframework.aop.Advisor;
import org.springframework.aop.framework.AopConfigException;
import org.springframework.beans.factory.BeanFactoryUtils;
import org.springframework.beans.factory.ListableBeanFactory;
import org.springframework.lang.Nullable;
Expand All @@ -40,6 +43,8 @@
*/
public class BeanFactoryAspectJAdvisorsBuilder {

private static final Log logger = LogFactory.getLog(BeanFactoryAspectJAdvisorsBuilder.class);

private final ListableBeanFactory beanFactory;

private final AspectJAdvisorFactory advisorFactory;
Expand Down Expand Up @@ -103,30 +108,37 @@ public List<Advisor> buildAspectJAdvisors() {
continue;
}
if (this.advisorFactory.isAspect(beanType)) {
aspectNames.add(beanName);
AspectMetadata amd = new AspectMetadata(beanType, beanName);
if (amd.getAjType().getPerClause().getKind() == PerClauseKind.SINGLETON) {
MetadataAwareAspectInstanceFactory factory =
new BeanFactoryAspectInstanceFactory(this.beanFactory, beanName);
List<Advisor> classAdvisors = this.advisorFactory.getAdvisors(factory);
if (this.beanFactory.isSingleton(beanName)) {
this.advisorsCache.put(beanName, classAdvisors);
try {
AspectMetadata amd = new AspectMetadata(beanType, beanName);
if (amd.getAjType().getPerClause().getKind() == PerClauseKind.SINGLETON) {
MetadataAwareAspectInstanceFactory factory =
new BeanFactoryAspectInstanceFactory(this.beanFactory, beanName);
List<Advisor> classAdvisors = this.advisorFactory.getAdvisors(factory);
if (this.beanFactory.isSingleton(beanName)) {
this.advisorsCache.put(beanName, classAdvisors);
}
else {
this.aspectFactoryCache.put(beanName, factory);
}
advisors.addAll(classAdvisors);
}
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);
advisors.addAll(this.advisorFactory.getAdvisors(factory));
}
advisors.addAll(classAdvisors);
aspectNames.add(beanName);
}
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");
catch (IllegalArgumentException | IllegalStateException | AopConfigException ex) {
if (logger.isDebugEnabled()) {
logger.debug("Ignoring incompatible aspect [" + beanType.getName() + "]: " + ex);
}
MetadataAwareAspectInstanceFactory factory =
new PrototypeAspectInstanceFactory(this.beanFactory, beanName);
this.aspectFactoryCache.put(beanName, factory);
advisors.addAll(this.advisorFactory.getAdvisors(factory));
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,10 @@
<property name="foo" value="bar"/>
</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>
Original file line number Diff line number Diff line change
Expand Up @@ -635,7 +635,7 @@ private Object processCacheEvicts(Collection<CacheOperationContext> contexts, bo
if (result instanceof CompletableFuture<?> future) {
return future.whenComplete((value, ex) -> {
if (ex == null) {
performCacheEvicts(applicable, result);
performCacheEvicts(applicable, value);
}
});
}
Expand Down Expand Up @@ -1117,7 +1117,7 @@ public Object processCacheEvicts(List<CacheOperationContext> contexts, @Nullable
ReactiveAdapter adapter = (result != null ? this.registry.getAdapter(result.getClass()) : null);
if (adapter != null) {
return adapter.fromPublisher(Mono.from(adapter.toPublisher(result))
.doOnSuccess(value -> performCacheEvicts(contexts, result)));
.doOnSuccess(value -> performCacheEvicts(contexts, value)));
}
return NOT_HANDLED;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2023 the original author or authors.
* Copyright 2002-2024 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -606,9 +606,9 @@ public CompletableFuture<TestBean> insertItem(TestBean item) {
return CompletableFuture.completedFuture(item);
}

@CacheEvict(cacheNames = "itemCache", allEntries = true)
public CompletableFuture<Void> clear() {
return CompletableFuture.completedFuture(null);
@CacheEvict(cacheNames = "itemCache", allEntries = true, condition = "#result > 0")
public CompletableFuture<Integer> clear() {
return CompletableFuture.completedFuture(1);
}
}

Expand Down Expand Up @@ -655,9 +655,9 @@ public Mono<TestBean> insertItem(TestBean item) {
return Mono.just(item);
}

@CacheEvict(cacheNames = "itemCache", allEntries = true)
public Mono<Void> clear() {
return Mono.empty();
@CacheEvict(cacheNames = "itemCache", allEntries = true, condition = "#result > 0")
public Mono<Integer> clear() {
return Mono.just(1);
}
}

Expand Down Expand Up @@ -706,9 +706,9 @@ public Flux<TestBean> insertItem(String id, List<TestBean> item) {
return Flux.fromIterable(item);
}

@CacheEvict(cacheNames = "itemCache", allEntries = true)
public Flux<Void> clear() {
return Flux.empty();
@CacheEvict(cacheNames = "itemCache", allEntries = true, condition = "#result > 0")
public Flux<Integer> clear() {
return Flux.just(1);
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2023 the original author or authors.
* Copyright 2002-2024 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -51,7 +51,9 @@ class ReactiveCachingTests {
LateCacheHitDeterminationConfig.class,
LateCacheHitDeterminationWithValueWrapperConfig.class})
void cacheHitDetermination(Class<?> configClass) {
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(configClass, ReactiveCacheableService.class);

AnnotationConfigApplicationContext ctx =
new AnnotationConfigApplicationContext(configClass, ReactiveCacheableService.class);
ReactiveCacheableService service = ctx.getBean(ReactiveCacheableService.class);

Object key = new Object();
Expand Down Expand Up @@ -117,7 +119,9 @@ void cacheHitDetermination(Class<?> configClass) {
LateCacheHitDeterminationConfig.class,
LateCacheHitDeterminationWithValueWrapperConfig.class})
void fluxCacheDoesntDependOnFirstRequest(Class<?> configClass) {
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(configClass, ReactiveCacheableService.class);

AnnotationConfigApplicationContext ctx =
new AnnotationConfigApplicationContext(configClass, ReactiveCacheableService.class);
ReactiveCacheableService service = ctx.getBean(ReactiveCacheableService.class);

Object key = new Object();
Expand All @@ -135,6 +139,7 @@ void fluxCacheDoesntDependOnFirstRequest(Class<?> configClass) {
ctx.close();
}


@CacheConfig(cacheNames = "first")
static class ReactiveCacheableService {

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2023-2023 the original author or authors.
* Copyright 2023-2024 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -28,8 +28,7 @@
import org.springframework.util.Assert;

/**
* {@link ClientHttpRequestFactory} implementation based on the Java
* {@link HttpClient}.
* {@link ClientHttpRequestFactory} implementation based on the Java {@link HttpClient}.
*
* @author Marten Deinum
* @author Arjen Poutsma
Expand Down Expand Up @@ -89,13 +88,11 @@ public void setReadTimeout(int readTimeout) {
}

/**
* Set the underlying {@code HttpClient}'s read timeout as a
* {@code Duration}.
* Set the underlying {@code HttpClient}'s read timeout as a {@code Duration}.
* <p>Default is the system's default timeout.
* @see java.net.http.HttpRequest.Builder#timeout
*/
public void setReadTimeout(Duration readTimeout) {
Assert.notNull(readTimeout, "ReadTimeout must not be null");
this.readTimeout = readTimeout;
}

Expand Down

0 comments on commit 2aabe23

Please sign in to comment.