Browse Source

Polish ReactiveMethodSecurity Support

- Changed annotation property to useAuthorizationManager
to match related XML support
- Moved support found in bean post-processors back into
interceptors directly. This reduces the number of components to
maintain and simplifies ongoing support
- Added @Deprecated annotation to indicate that applications
should use AuthorizationManagerBeforeReactiveMethodInterceptor and
AuthorizationManagerAfterReactiveMethodInterceptor instead. While
true that the new support does not support coroutines, the existing
coroutine support is problematic since it cannot be reliably paired
with other method interceptors
- Moved expression handler configuration to the constructors
- Constrain all method security interceptors to require publisher types
- Use ReactiveAdapter to check for single-value types as well

Issue gh-9401

Polish
Josh Cummings 3 years ago
parent
commit
e990174c89
30 changed files with 283 additions and 412 deletions
  1. 1 1
      config/src/main/java/org/springframework/security/config/annotation/method/configuration/EnableReactiveMethodSecurity.java
  2. 6 10
      config/src/main/java/org/springframework/security/config/annotation/method/configuration/ReactiveAuthorizationManagerMethodSecurityConfiguration.java
  3. 1 1
      config/src/main/java/org/springframework/security/config/annotation/method/configuration/ReactiveMethodSecuritySelector.java
  4. 5 0
      config/src/test/java/org/springframework/security/config/annotation/method/configuration/DelegatingReactiveMessageService.java
  5. 10 4
      config/src/test/java/org/springframework/security/config/annotation/method/configuration/EnableAuthorizationManagerReactiveMethodSecurityTests.java
  6. 2 0
      config/src/test/java/org/springframework/security/config/annotation/method/configuration/ReactiveMessageService.java
  7. 5 0
      core/src/main/java/org/springframework/security/access/prepost/PrePostAdviceReactiveMethodInterceptor.java
  8. 0 76
      core/src/main/java/org/springframework/security/authorization/method/AuthorizationAfterReactiveMethodInterceptor.java
  9. 0 59
      core/src/main/java/org/springframework/security/authorization/method/AuthorizationBeanFactoryPostProcessor.java
  10. 0 82
      core/src/main/java/org/springframework/security/authorization/method/AuthorizationBeforeReactiveMethodInterceptor.java
  11. 31 24
      core/src/main/java/org/springframework/security/authorization/method/AuthorizationManagerAfterReactiveMethodInterceptor.java
  12. 32 23
      core/src/main/java/org/springframework/security/authorization/method/AuthorizationManagerBeforeReactiveMethodInterceptor.java
  13. 2 2
      core/src/main/java/org/springframework/security/authorization/method/PostAuthorizeAuthorizationManager.java
  14. 8 4
      core/src/main/java/org/springframework/security/authorization/method/PostAuthorizeExpressionAttributeRegistry.java
  15. 10 7
      core/src/main/java/org/springframework/security/authorization/method/PostAuthorizeReactiveAuthorizationManager.java
  16. 2 2
      core/src/main/java/org/springframework/security/authorization/method/PostFilterAuthorizationMethodInterceptor.java
  17. 39 32
      core/src/main/java/org/springframework/security/authorization/method/PostFilterAuthorizationReactiveMethodInterceptor.java
  18. 8 4
      core/src/main/java/org/springframework/security/authorization/method/PostFilterExpressionAttributeRegistry.java
  19. 2 2
      core/src/main/java/org/springframework/security/authorization/method/PreAuthorizeAuthorizationManager.java
  20. 10 10
      core/src/main/java/org/springframework/security/authorization/method/PreAuthorizeExpressionAttributeRegistry.java
  21. 10 7
      core/src/main/java/org/springframework/security/authorization/method/PreAuthorizeReactiveAuthorizationManager.java
  22. 2 2
      core/src/main/java/org/springframework/security/authorization/method/PreFilterAuthorizationMethodInterceptor.java
  23. 36 34
      core/src/main/java/org/springframework/security/authorization/method/PreFilterAuthorizationReactiveMethodInterceptor.java
  24. 8 4
      core/src/main/java/org/springframework/security/authorization/method/PreFilterExpressionAttributeRegistry.java
  25. 20 3
      core/src/test/java/org/springframework/security/authorization/method/AuthorizationManagerAfterReactiveMethodInterceptorTests.java
  26. 20 3
      core/src/test/java/org/springframework/security/authorization/method/AuthorizationManagerBeforeReactiveMethodInterceptorTests.java
  27. 3 4
      core/src/test/java/org/springframework/security/authorization/method/PostAuthorizeReactiveAuthorizationManagerTests.java
  28. 4 4
      core/src/test/java/org/springframework/security/authorization/method/PostFilterAuthorizationReactiveMethodInterceptorTests.java
  29. 3 4
      core/src/test/java/org/springframework/security/authorization/method/PreAuthorizeReactiveAuthorizationManagerTests.java
  30. 3 4
      core/src/test/java/org/springframework/security/authorization/method/PreFilterAuthorizationReactiveMethodInterceptorTests.java

+ 1 - 1
config/src/main/java/org/springframework/security/config/annotation/method/configuration/EnableReactiveMethodSecurity.java

@@ -75,6 +75,6 @@ public @interface EnableReactiveMethodSecurity {
 	 * used.
 	 * @since 5.8
 	 */
-	boolean authorizationManager() default false;
+	boolean useAuthorizationManager() default false;
 
 }

+ 6 - 10
config/src/main/java/org/springframework/security/config/annotation/method/configuration/ReactiveAuthorizationManagerMethodSecurityConfiguration.java

@@ -45,17 +45,15 @@ final class ReactiveAuthorizationManagerMethodSecurityConfiguration {
 	@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
 	PreFilterAuthorizationReactiveMethodInterceptor preFilterInterceptor(
 			MethodSecurityExpressionHandler expressionHandler) {
-		PreFilterAuthorizationReactiveMethodInterceptor preFilter = new PreFilterAuthorizationReactiveMethodInterceptor();
-		preFilter.setExpressionHandler(expressionHandler);
-		return preFilter;
+		return new PreFilterAuthorizationReactiveMethodInterceptor(expressionHandler);
 	}
 
 	@Bean
 	@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
 	AuthorizationManagerBeforeReactiveMethodInterceptor preAuthorizeInterceptor(
 			MethodSecurityExpressionHandler expressionHandler) {
-		PreAuthorizeReactiveAuthorizationManager authorizationManager = new PreAuthorizeReactiveAuthorizationManager();
-		authorizationManager.setExpressionHandler(expressionHandler);
+		PreAuthorizeReactiveAuthorizationManager authorizationManager = new PreAuthorizeReactiveAuthorizationManager(
+				expressionHandler);
 		return AuthorizationManagerBeforeReactiveMethodInterceptor.preAuthorize(authorizationManager);
 	}
 
@@ -63,17 +61,15 @@ final class ReactiveAuthorizationManagerMethodSecurityConfiguration {
 	@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
 	PostFilterAuthorizationReactiveMethodInterceptor postFilterInterceptor(
 			MethodSecurityExpressionHandler expressionHandler) {
-		PostFilterAuthorizationReactiveMethodInterceptor postFilter = new PostFilterAuthorizationReactiveMethodInterceptor();
-		postFilter.setExpressionHandler(expressionHandler);
-		return postFilter;
+		return new PostFilterAuthorizationReactiveMethodInterceptor(expressionHandler);
 	}
 
 	@Bean
 	@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
 	AuthorizationManagerAfterReactiveMethodInterceptor postAuthorizeInterceptor(
 			MethodSecurityExpressionHandler expressionHandler) {
-		PostAuthorizeReactiveAuthorizationManager authorizationManager = new PostAuthorizeReactiveAuthorizationManager();
-		authorizationManager.setExpressionHandler(expressionHandler);
+		PostAuthorizeReactiveAuthorizationManager authorizationManager = new PostAuthorizeReactiveAuthorizationManager(
+				expressionHandler);
 		return AuthorizationManagerAfterReactiveMethodInterceptor.postAuthorize(authorizationManager);
 	}
 

+ 1 - 1
config/src/main/java/org/springframework/security/config/annotation/method/configuration/ReactiveMethodSecuritySelector.java

@@ -44,7 +44,7 @@ class ReactiveMethodSecuritySelector implements ImportSelector {
 		EnableReactiveMethodSecurity annotation = importMetadata.getAnnotations()
 				.get(EnableReactiveMethodSecurity.class).synthesize();
 		List<String> imports = new ArrayList<>(Arrays.asList(this.autoProxy.selectImports(importMetadata)));
-		if (annotation.authorizationManager()) {
+		if (annotation.useAuthorizationManager()) {
 			imports.add(ReactiveAuthorizationManagerMethodSecurityConfiguration.class.getName());
 		}
 		else {

+ 5 - 0
config/src/test/java/org/springframework/security/config/annotation/method/configuration/DelegatingReactiveMessageService.java

@@ -112,6 +112,11 @@ public class DelegatingReactiveMessageService implements ReactiveMessageService
 		return flux;
 	}
 
+	@PostFilter("filterObject.length > 5")
+	public Flux<String> fluxPostFilter(Flux<String> flux) {
+		return flux;
+	}
+
 	@Override
 	public Publisher<String> publisherFindById(long id) {
 		return this.delegate.publisherFindById(id);

+ 10 - 4
config/src/test/java/org/springframework/security/config/annotation/method/configuration/EnableAuthorizationManagerReactiveMethodSecurityTests.java

@@ -42,7 +42,7 @@ import static org.mockito.Mockito.reset;
 
 /**
  * Tests for {@link EnableReactiveMethodSecurity} with the
- * {@link EnableReactiveMethodSecurity#authorizationManager()} flag set to true.
+ * {@link EnableReactiveMethodSecurity#useAuthorizationManager()} flag set to true.
  *
  * @author Evgeniy Cheban
  */
@@ -79,8 +79,7 @@ public class EnableAuthorizationManagerReactiveMethodSecurityTests {
 				.withMessage("The returnType class java.lang.String on public abstract java.lang.String "
 						+ "org.springframework.security.config.annotation.method.configuration.ReactiveMessageService"
 						+ ".notPublisherPreAuthorizeFindById(long) must return an instance of org.reactivestreams"
-						+ ".Publisher (i.e. Mono / Flux) or the function must be a Kotlin coroutine "
-						+ "function in order to support Reactor Context");
+						+ ".Publisher (for example, a Mono or Flux) in order to support Reactor Context");
 	}
 
 	@Test
@@ -340,6 +339,13 @@ public class EnableAuthorizationManagerReactiveMethodSecurityTests {
 		StepVerifier.create(flux).expectNext("harold", "jonathan").expectError(AccessDeniedException.class).verify();
 	}
 
+	@Test
+	public void fluxPostFilterWhenFilteringThenWorks() {
+		Flux<String> flux = this.messageService.fluxPostFilter(Flux.just("harold", "jonathan", "michael", "pete", "bo"))
+				.contextWrite(this.withAdmin);
+		StepVerifier.create(flux).expectNext("harold", "jonathan", "michael").verifyComplete();
+	}
+
 	// Publisher tests
 	@Test
 	public void publisherWhenPermitAllThenAopDoesNotSubscribe() {
@@ -458,7 +464,7 @@ public class EnableAuthorizationManagerReactiveMethodSecurityTests {
 		return publisher(Flux.just(data));
 	}
 
-	@EnableReactiveMethodSecurity(authorizationManager = true)
+	@EnableReactiveMethodSecurity(useAuthorizationManager = true)
 	static class Config {
 
 		ReactiveMessageService delegate = mock(ReactiveMessageService.class);

+ 2 - 0
config/src/test/java/org/springframework/security/config/annotation/method/configuration/ReactiveMessageService.java

@@ -48,6 +48,8 @@ public interface ReactiveMessageService {
 
 	Flux<String> fluxManyAnnotations(Flux<String> flux);
 
+	Flux<String> fluxPostFilter(Flux<String> flux);
+
 	Publisher<String> publisherFindById(long id);
 
 	Publisher<String> publisherPreAuthorizeHasRoleFindById(long id);

+ 5 - 0
core/src/main/java/org/springframework/security/access/prepost/PrePostAdviceReactiveMethodInterceptor.java

@@ -52,7 +52,12 @@ import org.springframework.util.Assert;
  * @author Rob Winch
  * @author Eleftheria Stein
  * @since 5.0
+ * @deprecated Use
+ * {@link org.springframework.security.authorization.method.AuthorizationManagerBeforeReactiveMethodInterceptor}
+ * or
+ * {@link org.springframework.security.authorization.method.AuthorizationManagerAfterReactiveMethodInterceptor}
  */
+@Deprecated
 public class PrePostAdviceReactiveMethodInterceptor implements MethodInterceptor {
 
 	private Authentication anonymous = new AnonymousAuthenticationToken("key", "anonymous",

+ 0 - 76
core/src/main/java/org/springframework/security/authorization/method/AuthorizationAfterReactiveMethodInterceptor.java

@@ -1,76 +0,0 @@
-/*
- * Copyright 2002-2022 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.
- * You may obtain a copy of the License at
- *
- *      https://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.springframework.security.authorization.method;
-
-import java.lang.reflect.Method;
-
-import org.aopalliance.aop.Advice;
-import org.aopalliance.intercept.MethodInterceptor;
-import org.aopalliance.intercept.MethodInvocation;
-import reactor.core.publisher.Flux;
-import reactor.core.publisher.Mono;
-
-import org.springframework.aop.Pointcut;
-import org.springframework.aop.PointcutAdvisor;
-import org.springframework.aop.framework.AopInfrastructureBean;
-import org.springframework.core.Ordered;
-
-/**
- * A {@link MethodInterceptor} that wraps a {@link Mono} or a {@link Flux} using
- * <code>deffer</code> call.
- *
- * @author Evgeniy Cheban
- * @since 5.8
- */
-final class AuthorizationAfterReactiveMethodInterceptor
-		implements Ordered, MethodInterceptor, PointcutAdvisor, AopInfrastructureBean {
-
-	private final Pointcut pointcut = AuthorizationMethodPointcuts.forAllAnnotations();
-
-	private final int order = AuthorizationInterceptorsOrder.LAST.getOrder();
-
-	@Override
-	public Object invoke(MethodInvocation mi) throws Throwable {
-		Method method = mi.getMethod();
-		Class<?> returnType = method.getReturnType();
-		if (Mono.class.isAssignableFrom(returnType)) {
-			return Mono.defer(() -> ReactiveMethodInvocationUtils.proceed(mi));
-		}
-		return Flux.defer(() -> ReactiveMethodInvocationUtils.proceed(mi));
-	}
-
-	@Override
-	public Pointcut getPointcut() {
-		return this.pointcut;
-	}
-
-	@Override
-	public Advice getAdvice() {
-		return this;
-	}
-
-	@Override
-	public boolean isPerInstance() {
-		return true;
-	}
-
-	@Override
-	public int getOrder() {
-		return this.order;
-	}
-
-}

+ 0 - 59
core/src/main/java/org/springframework/security/authorization/method/AuthorizationBeanFactoryPostProcessor.java

@@ -1,59 +0,0 @@
-/*
- * Copyright 2002-2022 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.
- * You may obtain a copy of the License at
- *
- *      https://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.springframework.security.authorization.method;
-
-import org.springframework.beans.factory.config.BeanDefinition;
-import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
-import org.springframework.beans.factory.support.BeanDefinitionRegistry;
-import org.springframework.beans.factory.support.BeanDefinitionRegistryPostProcessor;
-import org.springframework.beans.factory.support.RootBeanDefinition;
-
-/**
- * Adds {@link AuthorizationBeforeReactiveMethodInterceptor} and
- * {@link AuthorizationAfterReactiveMethodInterceptor} bean definitions to the
- * {@link BeanDefinitionRegistry} if they have not already been added.
- *
- * @author Evgeniy Cheban
- * @since 5.8
- */
-final class AuthorizationBeanFactoryPostProcessor implements BeanDefinitionRegistryPostProcessor {
-
-	private static final String BEFORE_INTERCEPTOR_BEAN_NAME = "org.springframework.security.authorization.method.authorizationBeforeReactiveMethodInterceptor";
-
-	private static final String AFTER_INTERCEPTOR_BEAN_NAME = "org.springframework.security.authorization.method.authorizationAfterReactiveMethodInterceptor";
-
-	@Override
-	public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) {
-		if (!registry.containsBeanDefinition(BEFORE_INTERCEPTOR_BEAN_NAME)) {
-			RootBeanDefinition beforeInterceptor = new RootBeanDefinition(
-					AuthorizationBeforeReactiveMethodInterceptor.class);
-			beforeInterceptor.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
-			registry.registerBeanDefinition(BEFORE_INTERCEPTOR_BEAN_NAME, beforeInterceptor);
-		}
-		if (!registry.containsBeanDefinition(AFTER_INTERCEPTOR_BEAN_NAME)) {
-			RootBeanDefinition afterInterceptor = new RootBeanDefinition(
-					AuthorizationAfterReactiveMethodInterceptor.class);
-			afterInterceptor.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
-			registry.registerBeanDefinition(AFTER_INTERCEPTOR_BEAN_NAME, afterInterceptor);
-		}
-	}
-
-	@Override
-	public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {
-	}
-
-}

+ 0 - 82
core/src/main/java/org/springframework/security/authorization/method/AuthorizationBeforeReactiveMethodInterceptor.java

@@ -1,82 +0,0 @@
-/*
- * Copyright 2002-2022 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.
- * You may obtain a copy of the License at
- *
- *      https://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.springframework.security.authorization.method;
-
-import java.lang.reflect.Method;
-
-import org.aopalliance.aop.Advice;
-import org.aopalliance.intercept.MethodInterceptor;
-import org.aopalliance.intercept.MethodInvocation;
-import org.reactivestreams.Publisher;
-
-import org.springframework.aop.Pointcut;
-import org.springframework.aop.PointcutAdvisor;
-import org.springframework.aop.framework.AopInfrastructureBean;
-import org.springframework.core.Ordered;
-import org.springframework.core.ReactiveAdapter;
-import org.springframework.core.ReactiveAdapterRegistry;
-import org.springframework.util.Assert;
-
-/**
- * A {@link MethodInterceptor} which validates and transforms the return type for methods
- * that return a {@link Publisher}.
- *
- * @author Evgeniy Cheban
- * @since 5.8
- */
-final class AuthorizationBeforeReactiveMethodInterceptor
-		implements Ordered, MethodInterceptor, PointcutAdvisor, AopInfrastructureBean {
-
-	private final Pointcut pointcut = AuthorizationMethodPointcuts.forAllAnnotations();
-
-	private final int order = AuthorizationInterceptorsOrder.FIRST.getOrder();
-
-	@Override
-	public Object invoke(MethodInvocation mi) throws Throwable {
-		Method method = mi.getMethod();
-		Class<?> returnType = method.getReturnType();
-		Assert.state(Publisher.class.isAssignableFrom(returnType),
-				() -> "The returnType " + returnType + " on " + method
-						+ " must return an instance of org.reactivestreams.Publisher "
-						+ "(i.e. Mono / Flux) or the function must be a Kotlin coroutine "
-						+ "function in order to support Reactor Context");
-		Publisher<?> publisher = ReactiveMethodInvocationUtils.proceed(mi);
-		ReactiveAdapter adapter = ReactiveAdapterRegistry.getSharedInstance().getAdapter(returnType);
-		return (adapter != null) ? adapter.fromPublisher(publisher) : publisher;
-	}
-
-	@Override
-	public Pointcut getPointcut() {
-		return this.pointcut;
-	}
-
-	@Override
-	public Advice getAdvice() {
-		return this;
-	}
-
-	@Override
-	public boolean isPerInstance() {
-		return true;
-	}
-
-	@Override
-	public int getOrder() {
-		return this.order;
-	}
-
-}

+ 31 - 24
core/src/main/java/org/springframework/security/authorization/method/AuthorizationManagerAfterReactiveMethodInterceptor.java

@@ -16,6 +16,9 @@
 
 package org.springframework.security.authorization.method;
 
+import java.lang.reflect.Method;
+import java.util.function.Function;
+
 import org.aopalliance.aop.Advice;
 import org.aopalliance.intercept.MethodInterceptor;
 import org.aopalliance.intercept.MethodInvocation;
@@ -26,10 +29,9 @@ import reactor.core.publisher.Mono;
 import org.springframework.aop.Pointcut;
 import org.springframework.aop.PointcutAdvisor;
 import org.springframework.aop.framework.AopInfrastructureBean;
-import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
-import org.springframework.beans.factory.support.BeanDefinitionRegistry;
-import org.springframework.beans.factory.support.BeanDefinitionRegistryPostProcessor;
 import org.springframework.core.Ordered;
+import org.springframework.core.ReactiveAdapter;
+import org.springframework.core.ReactiveAdapterRegistry;
 import org.springframework.security.access.prepost.PostAuthorize;
 import org.springframework.security.authorization.ReactiveAuthorizationManager;
 import org.springframework.security.core.Authentication;
@@ -43,16 +45,14 @@ import org.springframework.util.Assert;
  * @author Evgeniy Cheban
  * @since 5.8
  */
-public final class AuthorizationManagerAfterReactiveMethodInterceptor implements Ordered, MethodInterceptor,
-		PointcutAdvisor, AopInfrastructureBean, BeanDefinitionRegistryPostProcessor {
-
-	private final AuthorizationBeanFactoryPostProcessor beanFactoryPostProcessor = new AuthorizationBeanFactoryPostProcessor();
+public final class AuthorizationManagerAfterReactiveMethodInterceptor
+		implements Ordered, MethodInterceptor, PointcutAdvisor, AopInfrastructureBean {
 
 	private final Pointcut pointcut;
 
 	private final ReactiveAuthorizationManager<MethodInvocationResult> authorizationManager;
 
-	private int order = AuthorizationInterceptorsOrder.POST_AUTHORIZE.getOrder();
+	private int order = AuthorizationInterceptorsOrder.LAST.getOrder();
 
 	/**
 	 * Creates an instance for the {@link PostAuthorize} annotation.
@@ -69,8 +69,10 @@ public final class AuthorizationManagerAfterReactiveMethodInterceptor implements
 	 */
 	public static AuthorizationManagerAfterReactiveMethodInterceptor postAuthorize(
 			ReactiveAuthorizationManager<MethodInvocationResult> authorizationManager) {
-		return new AuthorizationManagerAfterReactiveMethodInterceptor(
+		AuthorizationManagerAfterReactiveMethodInterceptor interceptor = new AuthorizationManagerAfterReactiveMethodInterceptor(
 				AuthorizationMethodPointcuts.forAnnotations(PostAuthorize.class), authorizationManager);
+		interceptor.setOrder(AuthorizationInterceptorsOrder.POST_AUTHORIZE.getOrder());
+		return interceptor;
 	}
 
 	/**
@@ -95,13 +97,28 @@ public final class AuthorizationManagerAfterReactiveMethodInterceptor implements
 	 */
 	@Override
 	public Object invoke(MethodInvocation mi) throws Throwable {
-		Publisher<?> publisher = ReactiveMethodInvocationUtils.proceed(mi);
+		Method method = mi.getMethod();
+		Class<?> type = method.getReturnType();
+		Assert.state(Publisher.class.isAssignableFrom(type),
+				() -> String.format("The returnType %s on %s must return an instance of org.reactivestreams.Publisher "
+						+ "(for example, a Mono or Flux) in order to support Reactor Context", type, method));
 		Mono<Authentication> authentication = ReactiveAuthenticationUtils.getAuthentication();
-		if (publisher instanceof Mono<?>) {
-			Mono<?> mono = (Mono<?>) publisher;
-			return mono.flatMap((result) -> postAuthorize(authentication, mi, result));
+		Function<Object, Mono<?>> postAuthorize = (result) -> postAuthorize(authentication, mi, result);
+		ReactiveAdapter adapter = ReactiveAdapterRegistry.getSharedInstance().getAdapter(type);
+		Publisher<?> publisher = ReactiveMethodInvocationUtils.proceed(mi);
+		if (isMultiValue(type, adapter)) {
+			Flux<?> flux = Flux.from(publisher).flatMap(postAuthorize);
+			return (adapter != null) ? adapter.fromPublisher(flux) : flux;
+		}
+		Mono<?> mono = Mono.from(publisher).flatMap(postAuthorize);
+		return (adapter != null) ? adapter.fromPublisher(mono) : mono;
+	}
+
+	private boolean isMultiValue(Class<?> returnType, ReactiveAdapter adapter) {
+		if (Flux.class.isAssignableFrom(returnType)) {
+			return true;
 		}
-		return Flux.from(publisher).flatMap((result) -> postAuthorize(authentication, mi, result));
+		return adapter == null || adapter.isMultiValue();
 	}
 
 	private Mono<?> postAuthorize(Mono<Authentication> authentication, MethodInvocation mi, Object result) {
@@ -133,14 +150,4 @@ public final class AuthorizationManagerAfterReactiveMethodInterceptor implements
 		this.order = order;
 	}
 
-	@Override
-	public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) {
-		this.beanFactoryPostProcessor.postProcessBeanDefinitionRegistry(registry);
-	}
-
-	@Override
-	public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {
-		this.beanFactoryPostProcessor.postProcessBeanFactory(beanFactory);
-	}
-
 }

+ 32 - 23
core/src/main/java/org/springframework/security/authorization/method/AuthorizationManagerBeforeReactiveMethodInterceptor.java

@@ -16,19 +16,21 @@
 
 package org.springframework.security.authorization.method;
 
+import java.lang.reflect.Method;
+
 import org.aopalliance.aop.Advice;
 import org.aopalliance.intercept.MethodInterceptor;
 import org.aopalliance.intercept.MethodInvocation;
 import org.reactivestreams.Publisher;
+import reactor.core.publisher.Flux;
 import reactor.core.publisher.Mono;
 
 import org.springframework.aop.Pointcut;
 import org.springframework.aop.PointcutAdvisor;
 import org.springframework.aop.framework.AopInfrastructureBean;
-import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
-import org.springframework.beans.factory.support.BeanDefinitionRegistry;
-import org.springframework.beans.factory.support.BeanDefinitionRegistryPostProcessor;
 import org.springframework.core.Ordered;
+import org.springframework.core.ReactiveAdapter;
+import org.springframework.core.ReactiveAdapterRegistry;
 import org.springframework.security.access.prepost.PreAuthorize;
 import org.springframework.security.authorization.ReactiveAuthorizationManager;
 import org.springframework.security.core.Authentication;
@@ -40,18 +42,17 @@ import org.springframework.util.Assert;
  * {@link ReactiveAuthorizationManager}.
  *
  * @author Evgeniy Cheban
+ * @author Josh Cummings
  * @since 5.8
  */
-public final class AuthorizationManagerBeforeReactiveMethodInterceptor implements Ordered, MethodInterceptor,
-		PointcutAdvisor, AopInfrastructureBean, BeanDefinitionRegistryPostProcessor {
-
-	private final AuthorizationBeanFactoryPostProcessor beanFactoryPostProcessor = new AuthorizationBeanFactoryPostProcessor();
+public final class AuthorizationManagerBeforeReactiveMethodInterceptor
+		implements Ordered, MethodInterceptor, PointcutAdvisor, AopInfrastructureBean {
 
 	private final Pointcut pointcut;
 
 	private final ReactiveAuthorizationManager<MethodInvocation> authorizationManager;
 
-	private int order = AuthorizationInterceptorsOrder.PRE_AUTHORIZE.getOrder();
+	private int order = AuthorizationInterceptorsOrder.FIRST.getOrder();
 
 	/**
 	 * Creates an instance for the {@link PreAuthorize} annotation.
@@ -68,8 +69,10 @@ public final class AuthorizationManagerBeforeReactiveMethodInterceptor implement
 	 */
 	public static AuthorizationManagerBeforeReactiveMethodInterceptor preAuthorize(
 			ReactiveAuthorizationManager<MethodInvocation> authorizationManager) {
-		return new AuthorizationManagerBeforeReactiveMethodInterceptor(
+		AuthorizationManagerBeforeReactiveMethodInterceptor interceptor = new AuthorizationManagerBeforeReactiveMethodInterceptor(
 				AuthorizationMethodPointcuts.forAnnotations(PreAuthorize.class), authorizationManager);
+		interceptor.setOrder(AuthorizationInterceptorsOrder.PRE_AUTHORIZE.getOrder());
+		return interceptor;
 	}
 
 	/**
@@ -94,13 +97,29 @@ public final class AuthorizationManagerBeforeReactiveMethodInterceptor implement
 	 */
 	@Override
 	public Object invoke(MethodInvocation mi) throws Throwable {
-		Publisher<?> publisher = ReactiveMethodInvocationUtils.proceed(mi);
+		Method method = mi.getMethod();
+		Class<?> type = method.getReturnType();
+		Assert.state(Publisher.class.isAssignableFrom(type),
+				() -> String.format("The returnType %s on %s must return an instance of org.reactivestreams.Publisher "
+						+ "(for example, a Mono or Flux) in order to support Reactor Context", type, method));
 		Mono<Authentication> authentication = ReactiveAuthenticationUtils.getAuthentication();
+		ReactiveAdapter adapter = ReactiveAdapterRegistry.getSharedInstance().getAdapter(type);
 		Mono<Void> preAuthorize = this.authorizationManager.verify(authentication, mi);
-		if (publisher instanceof Mono<?>) {
-			return preAuthorize.then((Mono<?>) publisher);
+		if (isMultiValue(type, adapter)) {
+			Publisher<?> publisher = Flux.defer(() -> ReactiveMethodInvocationUtils.proceed(mi));
+			Flux<?> result = preAuthorize.thenMany(publisher);
+			return (adapter != null) ? adapter.fromPublisher(result) : result;
+		}
+		Mono<?> publisher = Mono.defer(() -> ReactiveMethodInvocationUtils.proceed(mi));
+		Mono<?> result = preAuthorize.then(publisher);
+		return (adapter != null) ? adapter.fromPublisher(result) : result;
+	}
+
+	private boolean isMultiValue(Class<?> returnType, ReactiveAdapter adapter) {
+		if (Flux.class.isAssignableFrom(returnType)) {
+			return true;
 		}
-		return preAuthorize.thenMany(publisher);
+		return adapter == null || adapter.isMultiValue();
 	}
 
 	@Override
@@ -127,14 +146,4 @@ public final class AuthorizationManagerBeforeReactiveMethodInterceptor implement
 		this.order = order;
 	}
 
-	@Override
-	public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) {
-		this.beanFactoryPostProcessor.postProcessBeanDefinitionRegistry(registry);
-	}
-
-	@Override
-	public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {
-		this.beanFactoryPostProcessor.postProcessBeanFactory(beanFactory);
-	}
-
 }

+ 2 - 2
core/src/main/java/org/springframework/security/authorization/method/PostAuthorizeAuthorizationManager.java

@@ -39,14 +39,14 @@ import org.springframework.security.core.Authentication;
  */
 public final class PostAuthorizeAuthorizationManager implements AuthorizationManager<MethodInvocationResult> {
 
-	private final PostAuthorizeExpressionAttributeRegistry registry = new PostAuthorizeExpressionAttributeRegistry();
+	private PostAuthorizeExpressionAttributeRegistry registry = new PostAuthorizeExpressionAttributeRegistry();
 
 	/**
 	 * Use this the {@link MethodSecurityExpressionHandler}.
 	 * @param expressionHandler the {@link MethodSecurityExpressionHandler} to use
 	 */
 	public void setExpressionHandler(MethodSecurityExpressionHandler expressionHandler) {
-		this.registry.setExpressionHandler(expressionHandler);
+		this.registry = new PostAuthorizeExpressionAttributeRegistry(expressionHandler);
 	}
 
 	/**

+ 8 - 4
core/src/main/java/org/springframework/security/authorization/method/PostAuthorizeExpressionAttributeRegistry.java

@@ -35,17 +35,21 @@ import org.springframework.util.Assert;
  */
 final class PostAuthorizeExpressionAttributeRegistry extends AbstractExpressionAttributeRegistry<ExpressionAttribute> {
 
-	private MethodSecurityExpressionHandler expressionHandler = new DefaultMethodSecurityExpressionHandler();
+	private final MethodSecurityExpressionHandler expressionHandler;
 
-	MethodSecurityExpressionHandler getExpressionHandler() {
-		return this.expressionHandler;
+	PostAuthorizeExpressionAttributeRegistry() {
+		this(new DefaultMethodSecurityExpressionHandler());
 	}
 
-	void setExpressionHandler(MethodSecurityExpressionHandler expressionHandler) {
+	PostAuthorizeExpressionAttributeRegistry(MethodSecurityExpressionHandler expressionHandler) {
 		Assert.notNull(expressionHandler, "expressionHandler cannot be null");
 		this.expressionHandler = expressionHandler;
 	}
 
+	MethodSecurityExpressionHandler getExpressionHandler() {
+		return this.expressionHandler;
+	}
+
 	@NonNull
 	@Override
 	ExpressionAttribute resolveAttribute(Method method, Class<?> targetClass) {

+ 10 - 7
core/src/main/java/org/springframework/security/authorization/method/PostAuthorizeReactiveAuthorizationManager.java

@@ -19,11 +19,13 @@ package org.springframework.security.authorization.method;
 import org.aopalliance.intercept.MethodInvocation;
 import reactor.core.publisher.Mono;
 
+import org.springframework.security.access.expression.method.DefaultMethodSecurityExpressionHandler;
 import org.springframework.security.access.expression.method.MethodSecurityExpressionHandler;
 import org.springframework.security.access.prepost.PostAuthorize;
 import org.springframework.security.authorization.AuthorizationDecision;
 import org.springframework.security.authorization.ReactiveAuthorizationManager;
 import org.springframework.security.core.Authentication;
+import org.springframework.util.Assert;
 
 /**
  * A {@link ReactiveAuthorizationManager} which can determine if an {@link Authentication}
@@ -36,14 +38,15 @@ import org.springframework.security.core.Authentication;
 public final class PostAuthorizeReactiveAuthorizationManager
 		implements ReactiveAuthorizationManager<MethodInvocationResult> {
 
-	private final PostAuthorizeExpressionAttributeRegistry registry = new PostAuthorizeExpressionAttributeRegistry();
+	private final PostAuthorizeExpressionAttributeRegistry registry;
 
-	/**
-	 * Sets the {@link MethodSecurityExpressionHandler}.
-	 * @param expressionHandler the {@link MethodSecurityExpressionHandler} to use
-	 */
-	public void setExpressionHandler(MethodSecurityExpressionHandler expressionHandler) {
-		this.registry.setExpressionHandler(expressionHandler);
+	public PostAuthorizeReactiveAuthorizationManager() {
+		this(new DefaultMethodSecurityExpressionHandler());
+	}
+
+	public PostAuthorizeReactiveAuthorizationManager(MethodSecurityExpressionHandler expressionHandler) {
+		Assert.notNull(expressionHandler, "expressionHandler cannot be null");
+		this.registry = new PostAuthorizeExpressionAttributeRegistry(expressionHandler);
 	}
 
 	/**

+ 2 - 2
core/src/main/java/org/springframework/security/authorization/method/PostFilterAuthorizationMethodInterceptor.java

@@ -49,7 +49,7 @@ public final class PostFilterAuthorizationMethodInterceptor
 	private Supplier<Authentication> authentication = getAuthentication(
 			SecurityContextHolder.getContextHolderStrategy());
 
-	private final PostFilterExpressionAttributeRegistry registry = new PostFilterExpressionAttributeRegistry();
+	private PostFilterExpressionAttributeRegistry registry = new PostFilterExpressionAttributeRegistry();
 
 	private int order = AuthorizationInterceptorsOrder.POST_FILTER.getOrder();
 
@@ -68,7 +68,7 @@ public final class PostFilterAuthorizationMethodInterceptor
 	 * @param expressionHandler the {@link MethodSecurityExpressionHandler} to use
 	 */
 	public void setExpressionHandler(MethodSecurityExpressionHandler expressionHandler) {
-		this.registry.setExpressionHandler(expressionHandler);
+		this.registry = new PostFilterExpressionAttributeRegistry(expressionHandler);
 	}
 
 	/**

+ 39 - 32
core/src/main/java/org/springframework/security/authorization/method/PostFilterAuthorizationReactiveMethodInterceptor.java

@@ -16,6 +16,8 @@
 
 package org.springframework.security.authorization.method;
 
+import java.lang.reflect.Method;
+
 import org.aopalliance.aop.Advice;
 import org.aopalliance.intercept.MethodInterceptor;
 import org.aopalliance.intercept.MethodInvocation;
@@ -26,14 +28,15 @@ import reactor.core.publisher.Mono;
 import org.springframework.aop.Pointcut;
 import org.springframework.aop.PointcutAdvisor;
 import org.springframework.aop.framework.AopInfrastructureBean;
-import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
-import org.springframework.beans.factory.support.BeanDefinitionRegistry;
-import org.springframework.beans.factory.support.BeanDefinitionRegistryPostProcessor;
 import org.springframework.core.Ordered;
+import org.springframework.core.ReactiveAdapter;
+import org.springframework.core.ReactiveAdapterRegistry;
 import org.springframework.expression.EvaluationContext;
+import org.springframework.security.access.expression.method.DefaultMethodSecurityExpressionHandler;
 import org.springframework.security.access.expression.method.MethodSecurityExpressionHandler;
 import org.springframework.security.access.expression.method.MethodSecurityExpressionOperations;
 import org.springframework.security.access.prepost.PostFilter;
+import org.springframework.util.Assert;
 
 /**
  * A {@link MethodInterceptor} which filters the returned object from the
@@ -43,14 +46,12 @@ import org.springframework.security.access.prepost.PostFilter;
  * @author Evgeniy Cheban
  * @since 5.8
  */
-public final class PostFilterAuthorizationReactiveMethodInterceptor implements Ordered, MethodInterceptor,
-		PointcutAdvisor, AopInfrastructureBean, BeanDefinitionRegistryPostProcessor {
-
-	private final AuthorizationBeanFactoryPostProcessor beanFactoryPostProcessor = new AuthorizationBeanFactoryPostProcessor();
+public final class PostFilterAuthorizationReactiveMethodInterceptor
+		implements Ordered, MethodInterceptor, PointcutAdvisor, AopInfrastructureBean {
 
-	private final PostFilterExpressionAttributeRegistry registry = new PostFilterExpressionAttributeRegistry();
+	private final PostFilterExpressionAttributeRegistry registry;
 
-	private final Pointcut pointcut;
+	private final Pointcut pointcut = AuthorizationMethodPointcuts.forAnnotations(PostFilter.class);
 
 	private int order = AuthorizationInterceptorsOrder.POST_FILTER.getOrder();
 
@@ -58,15 +59,15 @@ public final class PostFilterAuthorizationReactiveMethodInterceptor implements O
 	 * Creates an instance.
 	 */
 	public PostFilterAuthorizationReactiveMethodInterceptor() {
-		this.pointcut = AuthorizationMethodPointcuts.forAnnotations(PostFilter.class);
+		this(new DefaultMethodSecurityExpressionHandler());
 	}
 
 	/**
-	 * Sets the {@link MethodSecurityExpressionHandler}.
-	 * @param expressionHandler the {@link MethodSecurityExpressionHandler} to use
+	 * Creates an instance.
 	 */
-	public void setExpressionHandler(MethodSecurityExpressionHandler expressionHandler) {
-		this.registry.setExpressionHandler(expressionHandler);
+	public PostFilterAuthorizationReactiveMethodInterceptor(MethodSecurityExpressionHandler expressionHandler) {
+		Assert.notNull(expressionHandler, "expressionHandler cannot be null");
+		this.registry = new PostFilterExpressionAttributeRegistry(expressionHandler);
 	}
 
 	/**
@@ -77,25 +78,41 @@ public final class PostFilterAuthorizationReactiveMethodInterceptor implements O
 	 */
 	@Override
 	public Object invoke(MethodInvocation mi) throws Throwable {
-		Publisher<?> publisher = ReactiveMethodInvocationUtils.proceed(mi);
 		ExpressionAttribute attribute = this.registry.getAttribute(mi);
 		if (attribute == ExpressionAttribute.NULL_ATTRIBUTE) {
-			return publisher;
+			return ReactiveMethodInvocationUtils.proceed(mi);
 		}
 		Mono<EvaluationContext> toInvoke = ReactiveAuthenticationUtils.getAuthentication()
 				.map((auth) -> this.registry.getExpressionHandler().createEvaluationContext(auth, mi));
-		if (publisher instanceof Mono<?>) {
-			return toInvoke.flatMap((ctx) -> filterMono((Mono<?>) publisher, ctx, attribute));
+		Method method = mi.getMethod();
+		Class<?> type = method.getReturnType();
+		Assert.state(Publisher.class.isAssignableFrom(type),
+				() -> String.format("The parameter type %s on %s must be an instance of org.reactivestreams.Publisher "
+						+ "(for example, a Mono or Flux) in order to support Reactor Context", type, method));
+		ReactiveAdapter adapter = ReactiveAdapterRegistry.getSharedInstance().getAdapter(type);
+		if (isMultiValue(type, adapter)) {
+			Publisher<?> publisher = Flux.defer(() -> ReactiveMethodInvocationUtils.proceed(mi));
+			Flux<?> flux = toInvoke.flatMapMany((ctx) -> filterMultiValue(publisher, ctx, attribute));
+			return (adapter != null) ? adapter.fromPublisher(flux) : flux;
+		}
+		Publisher<?> publisher = Mono.defer(() -> ReactiveMethodInvocationUtils.proceed(mi));
+		Mono<?> mono = toInvoke.flatMap((ctx) -> filterSingleValue(publisher, ctx, attribute));
+		return (adapter != null) ? adapter.fromPublisher(mono) : mono;
+	}
+
+	private boolean isMultiValue(Class<?> returnType, ReactiveAdapter adapter) {
+		if (Flux.class.isAssignableFrom(returnType)) {
+			return true;
 		}
-		return toInvoke.flatMapMany((ctx) -> filterPublisher(publisher, ctx, attribute));
+		return adapter == null || adapter.isMultiValue();
 	}
 
-	private Mono<?> filterMono(Mono<?> mono, EvaluationContext ctx, ExpressionAttribute attribute) {
-		return mono.doOnNext((result) -> setFilterObject(ctx, result))
+	private Mono<?> filterSingleValue(Publisher<?> publisher, EvaluationContext ctx, ExpressionAttribute attribute) {
+		return Mono.from(publisher).doOnNext((result) -> setFilterObject(ctx, result))
 				.flatMap((result) -> postFilter(ctx, result, attribute));
 	}
 
-	private Flux<?> filterPublisher(Publisher<?> publisher, EvaluationContext ctx, ExpressionAttribute attribute) {
+	private Flux<?> filterMultiValue(Publisher<?> publisher, EvaluationContext ctx, ExpressionAttribute attribute) {
 		return Flux.from(publisher).doOnNext((result) -> setFilterObject(ctx, result))
 				.flatMap((result) -> postFilter(ctx, result, attribute));
 	}
@@ -133,14 +150,4 @@ public final class PostFilterAuthorizationReactiveMethodInterceptor implements O
 		this.order = order;
 	}
 
-	@Override
-	public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) {
-		this.beanFactoryPostProcessor.postProcessBeanDefinitionRegistry(registry);
-	}
-
-	@Override
-	public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {
-		this.beanFactoryPostProcessor.postProcessBeanFactory(beanFactory);
-	}
-
 }

+ 8 - 4
core/src/main/java/org/springframework/security/authorization/method/PostFilterExpressionAttributeRegistry.java

@@ -34,17 +34,21 @@ import org.springframework.util.Assert;
  */
 final class PostFilterExpressionAttributeRegistry extends AbstractExpressionAttributeRegistry<ExpressionAttribute> {
 
-	private MethodSecurityExpressionHandler expressionHandler = new DefaultMethodSecurityExpressionHandler();
+	private final MethodSecurityExpressionHandler expressionHandler;
 
-	MethodSecurityExpressionHandler getExpressionHandler() {
-		return this.expressionHandler;
+	PostFilterExpressionAttributeRegistry() {
+		this.expressionHandler = new DefaultMethodSecurityExpressionHandler();
 	}
 
-	void setExpressionHandler(MethodSecurityExpressionHandler expressionHandler) {
+	PostFilterExpressionAttributeRegistry(MethodSecurityExpressionHandler expressionHandler) {
 		Assert.notNull(expressionHandler, "expressionHandler cannot be null");
 		this.expressionHandler = expressionHandler;
 	}
 
+	MethodSecurityExpressionHandler getExpressionHandler() {
+		return this.expressionHandler;
+	}
+
 	@NonNull
 	@Override
 	ExpressionAttribute resolveAttribute(Method method, Class<?> targetClass) {

+ 2 - 2
core/src/main/java/org/springframework/security/authorization/method/PreAuthorizeAuthorizationManager.java

@@ -39,14 +39,14 @@ import org.springframework.security.core.Authentication;
  */
 public final class PreAuthorizeAuthorizationManager implements AuthorizationManager<MethodInvocation> {
 
-	private final PreAuthorizeExpressionAttributeRegistry registry = new PreAuthorizeExpressionAttributeRegistry();
+	private PreAuthorizeExpressionAttributeRegistry registry = new PreAuthorizeExpressionAttributeRegistry();
 
 	/**
 	 * Sets the {@link MethodSecurityExpressionHandler}.
 	 * @param expressionHandler the {@link MethodSecurityExpressionHandler} to use
 	 */
 	public void setExpressionHandler(MethodSecurityExpressionHandler expressionHandler) {
-		this.registry.setExpressionHandler(expressionHandler);
+		this.registry = new PreAuthorizeExpressionAttributeRegistry(expressionHandler);
 	}
 
 	/**

+ 10 - 10
core/src/main/java/org/springframework/security/authorization/method/PreAuthorizeExpressionAttributeRegistry.java

@@ -35,7 +35,16 @@ import org.springframework.util.Assert;
  */
 final class PreAuthorizeExpressionAttributeRegistry extends AbstractExpressionAttributeRegistry<ExpressionAttribute> {
 
-	private MethodSecurityExpressionHandler expressionHandler = new DefaultMethodSecurityExpressionHandler();
+	private final MethodSecurityExpressionHandler expressionHandler;
+
+	PreAuthorizeExpressionAttributeRegistry() {
+		this.expressionHandler = new DefaultMethodSecurityExpressionHandler();
+	}
+
+	PreAuthorizeExpressionAttributeRegistry(MethodSecurityExpressionHandler expressionHandler) {
+		Assert.notNull(expressionHandler, "expressionHandler cannot be null");
+		this.expressionHandler = expressionHandler;
+	}
 
 	/**
 	 * Returns the {@link MethodSecurityExpressionHandler}.
@@ -45,15 +54,6 @@ final class PreAuthorizeExpressionAttributeRegistry extends AbstractExpressionAt
 		return this.expressionHandler;
 	}
 
-	/**
-	 * Sets the {@link MethodSecurityExpressionHandler}.
-	 * @param expressionHandler the {@link MethodSecurityExpressionHandler} to use
-	 */
-	void setExpressionHandler(MethodSecurityExpressionHandler expressionHandler) {
-		Assert.notNull(expressionHandler, "expressionHandler cannot be null");
-		this.expressionHandler = expressionHandler;
-	}
-
 	@NonNull
 	@Override
 	ExpressionAttribute resolveAttribute(Method method, Class<?> targetClass) {

+ 10 - 7
core/src/main/java/org/springframework/security/authorization/method/PreAuthorizeReactiveAuthorizationManager.java

@@ -19,11 +19,13 @@ package org.springframework.security.authorization.method;
 import org.aopalliance.intercept.MethodInvocation;
 import reactor.core.publisher.Mono;
 
+import org.springframework.security.access.expression.method.DefaultMethodSecurityExpressionHandler;
 import org.springframework.security.access.expression.method.MethodSecurityExpressionHandler;
 import org.springframework.security.access.prepost.PreAuthorize;
 import org.springframework.security.authorization.AuthorizationDecision;
 import org.springframework.security.authorization.ReactiveAuthorizationManager;
 import org.springframework.security.core.Authentication;
+import org.springframework.util.Assert;
 
 /**
  * A {@link ReactiveAuthorizationManager} which can determine if an {@link Authentication}
@@ -35,14 +37,15 @@ import org.springframework.security.core.Authentication;
  */
 public final class PreAuthorizeReactiveAuthorizationManager implements ReactiveAuthorizationManager<MethodInvocation> {
 
-	private final PreAuthorizeExpressionAttributeRegistry registry = new PreAuthorizeExpressionAttributeRegistry();
+	private final PreAuthorizeExpressionAttributeRegistry registry;
 
-	/**
-	 * Sets the {@link MethodSecurityExpressionHandler}.
-	 * @param expressionHandler the {@link MethodSecurityExpressionHandler} to use
-	 */
-	public void setExpressionHandler(MethodSecurityExpressionHandler expressionHandler) {
-		this.registry.setExpressionHandler(expressionHandler);
+	public PreAuthorizeReactiveAuthorizationManager() {
+		this(new DefaultMethodSecurityExpressionHandler());
+	}
+
+	public PreAuthorizeReactiveAuthorizationManager(MethodSecurityExpressionHandler expressionHandler) {
+		Assert.notNull(expressionHandler, "expressionHandler cannot be null");
+		this.registry = new PreAuthorizeExpressionAttributeRegistry(expressionHandler);
 	}
 
 	/**

+ 2 - 2
core/src/main/java/org/springframework/security/authorization/method/PreFilterAuthorizationMethodInterceptor.java

@@ -50,7 +50,7 @@ public final class PreFilterAuthorizationMethodInterceptor
 	private Supplier<Authentication> authentication = getAuthentication(
 			SecurityContextHolder.getContextHolderStrategy());
 
-	private final PreFilterExpressionAttributeRegistry registry = new PreFilterExpressionAttributeRegistry();
+	private PreFilterExpressionAttributeRegistry registry = new PreFilterExpressionAttributeRegistry();
 
 	private int order = AuthorizationInterceptorsOrder.PRE_FILTER.getOrder();
 
@@ -69,7 +69,7 @@ public final class PreFilterAuthorizationMethodInterceptor
 	 * @param expressionHandler the {@link MethodSecurityExpressionHandler} to use
 	 */
 	public void setExpressionHandler(MethodSecurityExpressionHandler expressionHandler) {
-		this.registry.setExpressionHandler(expressionHandler);
+		this.registry = new PreFilterExpressionAttributeRegistry(expressionHandler);
 	}
 
 	/**

+ 36 - 34
core/src/main/java/org/springframework/security/authorization/method/PreFilterAuthorizationReactiveMethodInterceptor.java

@@ -29,15 +29,13 @@ import org.springframework.aop.Pointcut;
 import org.springframework.aop.PointcutAdvisor;
 import org.springframework.aop.framework.AopInfrastructureBean;
 import org.springframework.aop.support.AopUtils;
-import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
-import org.springframework.beans.factory.support.BeanDefinitionRegistry;
-import org.springframework.beans.factory.support.BeanDefinitionRegistryPostProcessor;
 import org.springframework.core.Ordered;
 import org.springframework.core.ParameterNameDiscoverer;
 import org.springframework.core.ReactiveAdapter;
 import org.springframework.core.ReactiveAdapterRegistry;
 import org.springframework.expression.EvaluationContext;
 import org.springframework.expression.Expression;
+import org.springframework.security.access.expression.method.DefaultMethodSecurityExpressionHandler;
 import org.springframework.security.access.expression.method.MethodSecurityExpressionHandler;
 import org.springframework.security.access.expression.method.MethodSecurityExpressionOperations;
 import org.springframework.security.access.prepost.PreFilter;
@@ -52,12 +50,10 @@ import org.springframework.util.StringUtils;
  * @author Evgeniy Cheban
  * @since 5.8
  */
-public final class PreFilterAuthorizationReactiveMethodInterceptor implements Ordered, MethodInterceptor,
-		PointcutAdvisor, AopInfrastructureBean, BeanDefinitionRegistryPostProcessor {
+public final class PreFilterAuthorizationReactiveMethodInterceptor
+		implements Ordered, MethodInterceptor, PointcutAdvisor, AopInfrastructureBean {
 
-	private final AuthorizationBeanFactoryPostProcessor beanFactoryPostProcessor = new AuthorizationBeanFactoryPostProcessor();
-
-	private final PreFilterExpressionAttributeRegistry registry = new PreFilterExpressionAttributeRegistry();
+	private final PreFilterExpressionAttributeRegistry registry;
 
 	private final Pointcut pointcut = AuthorizationMethodPointcuts.forAnnotations(PreFilter.class);
 
@@ -65,12 +61,16 @@ public final class PreFilterAuthorizationReactiveMethodInterceptor implements Or
 
 	private int order = AuthorizationInterceptorsOrder.PRE_FILTER.getOrder();
 
+	public PreFilterAuthorizationReactiveMethodInterceptor() {
+		this(new DefaultMethodSecurityExpressionHandler());
+	}
+
 	/**
-	 * Sets the {@link MethodSecurityExpressionHandler}.
-	 * @param expressionHandler the {@link MethodSecurityExpressionHandler} to use
+	 * Creates an instance.
 	 */
-	public void setExpressionHandler(MethodSecurityExpressionHandler expressionHandler) {
-		this.registry.setExpressionHandler(expressionHandler);
+	public PreFilterAuthorizationReactiveMethodInterceptor(MethodSecurityExpressionHandler expressionHandler) {
+		Assert.notNull(expressionHandler, "expressionHandler cannot be null");
+		this.registry = new PreFilterExpressionAttributeRegistry(expressionHandler);
 	}
 
 	/**
@@ -92,23 +92,28 @@ public final class PreFilterAuthorizationReactiveMethodInterceptor implements Or
 	public Object invoke(MethodInvocation mi) throws Throwable {
 		PreFilterExpressionAttributeRegistry.PreFilterExpressionAttribute attribute = this.registry.getAttribute(mi);
 		if (attribute == PreFilterExpressionAttributeRegistry.PreFilterExpressionAttribute.NULL_ATTRIBUTE) {
-			return ReactiveMethodInvocationUtils.<Publisher<?>>proceed(mi);
+			return ReactiveMethodInvocationUtils.proceed(mi);
 		}
 		FilterTarget filterTarget = findFilterTarget(attribute.getFilterTarget(), mi);
 		Mono<EvaluationContext> toInvoke = ReactiveAuthenticationUtils.getAuthentication()
 				.map((auth) -> this.registry.getExpressionHandler().createEvaluationContext(auth, mi));
-		if (filterTarget.value instanceof Mono<?>) {
-			mi.getArguments()[filterTarget.index] = toInvoke
-					.flatMap((ctx) -> filterMono((Mono<?>) filterTarget.value, attribute.getExpression(), ctx));
+		Method method = mi.getMethod();
+		Class<?> type = filterTarget.value.getClass();
+		Assert.state(Publisher.class.isAssignableFrom(type),
+				() -> String.format("The parameter type %s on %s must be an instance of org.reactivestreams.Publisher "
+						+ "(for example, a Mono or Flux) in order to support Reactor Context", type, method));
+		ReactiveAdapter adapter = ReactiveAdapterRegistry.getSharedInstance().getAdapter(type);
+		if (isMultiValue(type, adapter)) {
+			Flux<?> result = toInvoke
+					.flatMapMany((ctx) -> filterMultiValue(filterTarget.value, attribute.getExpression(), ctx));
+			mi.getArguments()[filterTarget.index] = (adapter != null) ? adapter.fromPublisher(result) : result;
 		}
 		else {
-			Flux<?> result = toInvoke
-					.flatMapMany((ctx) -> filterPublisher(filterTarget.value, attribute.getExpression(), ctx));
-			ReactiveAdapter adapter = ReactiveAdapterRegistry.getSharedInstance()
-					.getAdapter(filterTarget.value.getClass());
+			Mono<?> result = toInvoke
+					.flatMap((ctx) -> filterSingleValue(filterTarget.value, attribute.getExpression(), ctx));
 			mi.getArguments()[filterTarget.index] = (adapter != null) ? adapter.fromPublisher(result) : result;
 		}
-		return ReactiveMethodInvocationUtils.<Publisher<?>>proceed(mi);
+		return ReactiveMethodInvocationUtils.proceed(mi);
 	}
 
 	private FilterTarget findFilterTarget(String name, MethodInvocation mi) {
@@ -143,16 +148,23 @@ public final class PreFilterAuthorizationReactiveMethodInterceptor implements Or
 		return new FilterTarget((Publisher<?>) value, index);
 	}
 
-	private Mono<?> filterMono(Mono<?> filterTarget, Expression filterExpression, EvaluationContext ctx) {
+	private boolean isMultiValue(Class<?> returnType, ReactiveAdapter adapter) {
+		if (Flux.class.isAssignableFrom(returnType)) {
+			return true;
+		}
+		return adapter == null || adapter.isMultiValue();
+	}
+
+	private Mono<?> filterSingleValue(Publisher<?> filterTarget, Expression filterExpression, EvaluationContext ctx) {
 		MethodSecurityExpressionOperations rootObject = (MethodSecurityExpressionOperations) ctx.getRootObject()
 				.getValue();
-		return filterTarget.filterWhen((filterObject) -> {
+		return Mono.from(filterTarget).filterWhen((filterObject) -> {
 			rootObject.setFilterObject(filterObject);
 			return ReactiveExpressionUtils.evaluateAsBoolean(filterExpression, ctx);
 		});
 	}
 
-	private Flux<?> filterPublisher(Publisher<?> filterTarget, Expression filterExpression, EvaluationContext ctx) {
+	private Flux<?> filterMultiValue(Publisher<?> filterTarget, Expression filterExpression, EvaluationContext ctx) {
 		MethodSecurityExpressionOperations rootObject = (MethodSecurityExpressionOperations) ctx.getRootObject()
 				.getValue();
 		return Flux.from(filterTarget).filterWhen((filterObject) -> {
@@ -185,16 +197,6 @@ public final class PreFilterAuthorizationReactiveMethodInterceptor implements Or
 		this.order = order;
 	}
 
-	@Override
-	public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) {
-		this.beanFactoryPostProcessor.postProcessBeanDefinitionRegistry(registry);
-	}
-
-	@Override
-	public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {
-		this.beanFactoryPostProcessor.postProcessBeanFactory(beanFactory);
-	}
-
 	private static final class FilterTarget {
 
 		private final Publisher<?> value;

+ 8 - 4
core/src/main/java/org/springframework/security/authorization/method/PreFilterExpressionAttributeRegistry.java

@@ -35,17 +35,21 @@ import org.springframework.util.Assert;
 final class PreFilterExpressionAttributeRegistry
 		extends AbstractExpressionAttributeRegistry<PreFilterExpressionAttributeRegistry.PreFilterExpressionAttribute> {
 
-	private MethodSecurityExpressionHandler expressionHandler = new DefaultMethodSecurityExpressionHandler();
+	private final MethodSecurityExpressionHandler expressionHandler;
 
-	MethodSecurityExpressionHandler getExpressionHandler() {
-		return this.expressionHandler;
+	PreFilterExpressionAttributeRegistry() {
+		this.expressionHandler = new DefaultMethodSecurityExpressionHandler();
 	}
 
-	void setExpressionHandler(MethodSecurityExpressionHandler expressionHandler) {
+	PreFilterExpressionAttributeRegistry(MethodSecurityExpressionHandler expressionHandler) {
 		Assert.notNull(expressionHandler, "expressionHandler cannot be null");
 		this.expressionHandler = expressionHandler;
 	}
 
+	MethodSecurityExpressionHandler getExpressionHandler() {
+		return this.expressionHandler;
+	}
+
 	@NonNull
 	@Override
 	PreFilterExpressionAttribute resolveAttribute(Method method, Class<?> targetClass) {

+ 20 - 3
core/src/test/java/org/springframework/security/authorization/method/AuthorizationManagerAfterReactiveMethodInterceptorTests.java

@@ -24,6 +24,7 @@ import reactor.core.publisher.Mono;
 
 import org.springframework.aop.Pointcut;
 import org.springframework.security.access.AccessDeniedException;
+import org.springframework.security.access.intercept.method.MockMethodInvocation;
 import org.springframework.security.authorization.ReactiveAuthorizationManager;
 
 import static org.assertj.core.api.Assertions.assertThat;
@@ -32,6 +33,7 @@ import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException
 import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.BDDMockito.given;
 import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.spy;
 import static org.mockito.Mockito.times;
 import static org.mockito.Mockito.verify;
 
@@ -59,7 +61,8 @@ public class AuthorizationManagerAfterReactiveMethodInterceptorTests {
 
 	@Test
 	public void invokeMonoWhenMockReactiveAuthorizationManagerThenVerify() throws Throwable {
-		MethodInvocation mockMethodInvocation = mock(MethodInvocation.class);
+		MethodInvocation mockMethodInvocation = spy(
+				new MockMethodInvocation(new Sample(), Sample.class.getDeclaredMethod("mono")));
 		given(mockMethodInvocation.proceed()).willReturn(Mono.just("john"));
 		ReactiveAuthorizationManager<MethodInvocationResult> mockReactiveAuthorizationManager = mock(
 				ReactiveAuthorizationManager.class);
@@ -74,7 +77,8 @@ public class AuthorizationManagerAfterReactiveMethodInterceptorTests {
 
 	@Test
 	public void invokeFluxWhenMockReactiveAuthorizationManagerThenVerify() throws Throwable {
-		MethodInvocation mockMethodInvocation = mock(MethodInvocation.class);
+		MethodInvocation mockMethodInvocation = spy(
+				new MockMethodInvocation(new Sample(), Sample.class.getDeclaredMethod("flux")));
 		given(mockMethodInvocation.proceed()).willReturn(Flux.just("john", "bob"));
 		ReactiveAuthorizationManager<MethodInvocationResult> mockReactiveAuthorizationManager = mock(
 				ReactiveAuthorizationManager.class);
@@ -89,7 +93,8 @@ public class AuthorizationManagerAfterReactiveMethodInterceptorTests {
 
 	@Test
 	public void invokeWhenMockReactiveAuthorizationManagerDeniedThenAccessDeniedException() throws Throwable {
-		MethodInvocation mockMethodInvocation = mock(MethodInvocation.class);
+		MethodInvocation mockMethodInvocation = spy(
+				new MockMethodInvocation(new Sample(), Sample.class.getDeclaredMethod("mono")));
 		given(mockMethodInvocation.proceed()).willReturn(Mono.just("john"));
 		ReactiveAuthorizationManager<MethodInvocationResult> mockReactiveAuthorizationManager = mock(
 				ReactiveAuthorizationManager.class);
@@ -104,4 +109,16 @@ public class AuthorizationManagerAfterReactiveMethodInterceptorTests {
 		verify(mockReactiveAuthorizationManager).verify(any(), any());
 	}
 
+	class Sample {
+
+		Mono<String> mono() {
+			return Mono.just("john");
+		}
+
+		Flux<String> flux() {
+			return Flux.just("john", "bob");
+		}
+
+	}
+
 }

+ 20 - 3
core/src/test/java/org/springframework/security/authorization/method/AuthorizationManagerBeforeReactiveMethodInterceptorTests.java

@@ -24,6 +24,7 @@ import reactor.core.publisher.Mono;
 
 import org.springframework.aop.Pointcut;
 import org.springframework.security.access.AccessDeniedException;
+import org.springframework.security.access.intercept.method.MockMethodInvocation;
 import org.springframework.security.authorization.ReactiveAuthorizationManager;
 
 import static org.assertj.core.api.Assertions.assertThat;
@@ -33,6 +34,7 @@ import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.ArgumentMatchers.eq;
 import static org.mockito.BDDMockito.given;
 import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.spy;
 import static org.mockito.Mockito.verify;
 
 /**
@@ -60,7 +62,8 @@ public class AuthorizationManagerBeforeReactiveMethodInterceptorTests {
 
 	@Test
 	public void invokeMonoWhenMockReactiveAuthorizationManagerThenVerify() throws Throwable {
-		MethodInvocation mockMethodInvocation = mock(MethodInvocation.class);
+		MethodInvocation mockMethodInvocation = spy(
+				new MockMethodInvocation(new Sample(), Sample.class.getDeclaredMethod("mono")));
 		given(mockMethodInvocation.proceed()).willReturn(Mono.just("john"));
 		ReactiveAuthorizationManager<MethodInvocation> mockReactiveAuthorizationManager = mock(
 				ReactiveAuthorizationManager.class);
@@ -75,7 +78,8 @@ public class AuthorizationManagerBeforeReactiveMethodInterceptorTests {
 
 	@Test
 	public void invokeFluxWhenMockReactiveAuthorizationManagerThenVerify() throws Throwable {
-		MethodInvocation mockMethodInvocation = mock(MethodInvocation.class);
+		MethodInvocation mockMethodInvocation = spy(
+				new MockMethodInvocation(new Sample(), Sample.class.getDeclaredMethod("flux")));
 		given(mockMethodInvocation.proceed()).willReturn(Flux.just("john", "bob"));
 		ReactiveAuthorizationManager<MethodInvocation> mockReactiveAuthorizationManager = mock(
 				ReactiveAuthorizationManager.class);
@@ -90,7 +94,8 @@ public class AuthorizationManagerBeforeReactiveMethodInterceptorTests {
 
 	@Test
 	public void invokeWhenMockReactiveAuthorizationManagerDeniedThenAccessDeniedException() throws Throwable {
-		MethodInvocation mockMethodInvocation = mock(MethodInvocation.class);
+		MethodInvocation mockMethodInvocation = spy(
+				new MockMethodInvocation(new Sample(), Sample.class.getDeclaredMethod("mono")));
 		given(mockMethodInvocation.proceed()).willReturn(Mono.just("john"));
 		ReactiveAuthorizationManager<MethodInvocation> mockReactiveAuthorizationManager = mock(
 				ReactiveAuthorizationManager.class);
@@ -105,4 +110,16 @@ public class AuthorizationManagerBeforeReactiveMethodInterceptorTests {
 		verify(mockReactiveAuthorizationManager).verify(any(), eq(mockMethodInvocation));
 	}
 
+	class Sample {
+
+		Mono<String> mono() {
+			return Mono.just("john");
+		}
+
+		Flux<String> flux() {
+			return Flux.just("john", "bob");
+		}
+
+	}
+
 }

+ 3 - 4
core/src/test/java/org/springframework/security/authorization/method/PostAuthorizeReactiveAuthorizationManagerTests.java

@@ -48,15 +48,14 @@ public class PostAuthorizeReactiveAuthorizationManagerTests {
 	@Test
 	public void setExpressionHandlerWhenNotNullThenSetsExpressionHandler() {
 		MethodSecurityExpressionHandler expressionHandler = new DefaultMethodSecurityExpressionHandler();
-		PostAuthorizeReactiveAuthorizationManager manager = new PostAuthorizeReactiveAuthorizationManager();
-		manager.setExpressionHandler(expressionHandler);
+		PostAuthorizeReactiveAuthorizationManager manager = new PostAuthorizeReactiveAuthorizationManager(
+				expressionHandler);
 		assertThat(manager).extracting("registry").extracting("expressionHandler").isEqualTo(expressionHandler);
 	}
 
 	@Test
 	public void setExpressionHandlerWhenNullThenException() {
-		PostAuthorizeReactiveAuthorizationManager manager = new PostAuthorizeReactiveAuthorizationManager();
-		assertThatIllegalArgumentException().isThrownBy(() -> manager.setExpressionHandler(null))
+		assertThatIllegalArgumentException().isThrownBy(() -> new PostAuthorizeReactiveAuthorizationManager(null))
 				.withMessage("expressionHandler cannot be null");
 	}
 

+ 4 - 4
core/src/test/java/org/springframework/security/authorization/method/PostFilterAuthorizationReactiveMethodInterceptorTests.java

@@ -44,15 +44,15 @@ public class PostFilterAuthorizationReactiveMethodInterceptorTests {
 	@Test
 	public void setExpressionHandlerWhenNotNullThenSetsExpressionHandler() {
 		MethodSecurityExpressionHandler expressionHandler = new DefaultMethodSecurityExpressionHandler();
-		PostFilterAuthorizationReactiveMethodInterceptor interceptor = new PostFilterAuthorizationReactiveMethodInterceptor();
-		interceptor.setExpressionHandler(expressionHandler);
+		PostFilterAuthorizationReactiveMethodInterceptor interceptor = new PostFilterAuthorizationReactiveMethodInterceptor(
+				expressionHandler);
 		assertThat(interceptor).extracting("registry").extracting("expressionHandler").isEqualTo(expressionHandler);
 	}
 
 	@Test
 	public void setExpressionHandlerWhenNullThenException() {
-		PostFilterAuthorizationReactiveMethodInterceptor interceptor = new PostFilterAuthorizationReactiveMethodInterceptor();
-		assertThatIllegalArgumentException().isThrownBy(() -> interceptor.setExpressionHandler(null))
+		assertThatIllegalArgumentException()
+				.isThrownBy(() -> new PostFilterAuthorizationReactiveMethodInterceptor(null))
 				.withMessage("expressionHandler cannot be null");
 	}
 

+ 3 - 4
core/src/test/java/org/springframework/security/authorization/method/PreAuthorizeReactiveAuthorizationManagerTests.java

@@ -45,15 +45,14 @@ public class PreAuthorizeReactiveAuthorizationManagerTests {
 	@Test
 	public void setExpressionHandlerWhenNotNullThenSetsExpressionHandler() {
 		MethodSecurityExpressionHandler expressionHandler = new DefaultMethodSecurityExpressionHandler();
-		PreAuthorizeReactiveAuthorizationManager manager = new PreAuthorizeReactiveAuthorizationManager();
-		manager.setExpressionHandler(expressionHandler);
+		PreAuthorizeReactiveAuthorizationManager manager = new PreAuthorizeReactiveAuthorizationManager(
+				expressionHandler);
 		assertThat(manager).extracting("registry").extracting("expressionHandler").isEqualTo(expressionHandler);
 	}
 
 	@Test
 	public void setExpressionHandlerWhenNullThenException() {
-		PreAuthorizeReactiveAuthorizationManager manager = new PreAuthorizeReactiveAuthorizationManager();
-		assertThatIllegalArgumentException().isThrownBy(() -> manager.setExpressionHandler(null))
+		assertThatIllegalArgumentException().isThrownBy(() -> new PreAuthorizeReactiveAuthorizationManager(null))
 				.withMessage("expressionHandler cannot be null");
 	}
 

+ 3 - 4
core/src/test/java/org/springframework/security/authorization/method/PreFilterAuthorizationReactiveMethodInterceptorTests.java

@@ -46,15 +46,14 @@ public class PreFilterAuthorizationReactiveMethodInterceptorTests {
 	@Test
 	public void setExpressionHandlerWhenNotNullThenSetsExpressionHandler() {
 		MethodSecurityExpressionHandler expressionHandler = new DefaultMethodSecurityExpressionHandler();
-		PreFilterAuthorizationReactiveMethodInterceptor interceptor = new PreFilterAuthorizationReactiveMethodInterceptor();
-		interceptor.setExpressionHandler(expressionHandler);
+		PreFilterAuthorizationReactiveMethodInterceptor interceptor = new PreFilterAuthorizationReactiveMethodInterceptor(
+				expressionHandler);
 		assertThat(interceptor).extracting("registry").extracting("expressionHandler").isEqualTo(expressionHandler);
 	}
 
 	@Test
 	public void setExpressionHandlerWhenNullThenException() {
-		PreFilterAuthorizationReactiveMethodInterceptor interceptor = new PreFilterAuthorizationReactiveMethodInterceptor();
-		assertThatIllegalArgumentException().isThrownBy(() -> interceptor.setExpressionHandler(null))
+		assertThatIllegalArgumentException().isThrownBy(() -> new PreFilterAuthorizationReactiveMethodInterceptor(null))
 				.withMessage("expressionHandler cannot be null");
 	}