Move AOP auto-configuration into spring-boot-autoconfigure
This commit is contained in:
committed by
Phillip Webb
parent
a527e028a7
commit
5b12959189
@@ -0,0 +1,87 @@
|
||||
/*
|
||||
* Copyright 2012-2025 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.boot.autoconfigure.aop;
|
||||
|
||||
import org.aspectj.weaver.Advice;
|
||||
|
||||
import org.springframework.aop.config.AopConfigUtils;
|
||||
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
|
||||
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
|
||||
import org.springframework.boot.autoconfigure.AutoConfiguration;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnBooleanProperty;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingClass;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.EnableAspectJAutoProxy;
|
||||
|
||||
/**
|
||||
* {@link org.springframework.boot.autoconfigure.EnableAutoConfiguration
|
||||
* Auto-configuration} for Spring's AOP support. Equivalent to enabling
|
||||
* {@link EnableAspectJAutoProxy @EnableAspectJAutoProxy} in your configuration.
|
||||
* <p>
|
||||
* The configuration will not be activated if {@literal spring.aop.auto=false}. The
|
||||
* {@literal proxyTargetClass} attribute will be {@literal true}, by default, but can be
|
||||
* overridden by specifying {@literal spring.aop.proxy-target-class=false}.
|
||||
*
|
||||
* @author Dave Syer
|
||||
* @author Josh Long
|
||||
* @since 1.0.0
|
||||
* @see EnableAspectJAutoProxy
|
||||
*/
|
||||
@AutoConfiguration
|
||||
@ConditionalOnBooleanProperty(name = "spring.aop.auto", matchIfMissing = true)
|
||||
public class AopAutoConfiguration {
|
||||
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
@ConditionalOnClass(Advice.class)
|
||||
static class AspectJAutoProxyingConfiguration {
|
||||
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
@EnableAspectJAutoProxy(proxyTargetClass = false)
|
||||
@ConditionalOnBooleanProperty(name = "spring.aop.proxy-target-class", havingValue = false)
|
||||
static class JdkDynamicAutoProxyConfiguration {
|
||||
|
||||
}
|
||||
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
@EnableAspectJAutoProxy(proxyTargetClass = true)
|
||||
@ConditionalOnBooleanProperty(name = "spring.aop.proxy-target-class", matchIfMissing = true)
|
||||
static class CglibAutoProxyConfiguration {
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
@ConditionalOnMissingClass("org.aspectj.weaver.Advice")
|
||||
@ConditionalOnBooleanProperty(name = "spring.aop.proxy-target-class", matchIfMissing = true)
|
||||
static class ClassProxyingConfiguration {
|
||||
|
||||
@Bean
|
||||
static BeanFactoryPostProcessor forceAutoProxyCreatorToUseClassProxying() {
|
||||
return (beanFactory) -> {
|
||||
if (beanFactory instanceof BeanDefinitionRegistry registry) {
|
||||
AopConfigUtils.registerAutoProxyCreatorIfNecessary(registry);
|
||||
AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
/*
|
||||
* Copyright 2012-2019 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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Auto-configuration for Spring AOP.
|
||||
*/
|
||||
package org.springframework.boot.autoconfigure.aop;
|
||||
@@ -287,6 +287,18 @@
|
||||
"level": "error"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "spring.aop.auto",
|
||||
"type": "java.lang.Boolean",
|
||||
"description": "Add @EnableAspectJAutoProxy.",
|
||||
"defaultValue": true
|
||||
},
|
||||
{
|
||||
"name": "spring.aop.proxy-target-class",
|
||||
"type": "java.lang.Boolean",
|
||||
"description": "Whether subclass-based (CGLIB) proxies are to be created (true), as opposed to standard Java interface-based proxies (false).",
|
||||
"defaultValue": true
|
||||
},
|
||||
{
|
||||
"name": "spring.application.admin.enabled",
|
||||
"type": "java.lang.Boolean",
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
org.springframework.boot.autoconfigure.admin.SpringApplicationAdminJmxAutoConfiguration
|
||||
org.springframework.boot.autoconfigure.aop.AopAutoConfiguration
|
||||
org.springframework.boot.autoconfigure.availability.ApplicationAvailabilityAutoConfiguration
|
||||
org.springframework.boot.autoconfigure.context.ConfigurationPropertiesAutoConfiguration
|
||||
org.springframework.boot.autoconfigure.context.LifecycleAutoConfiguration
|
||||
|
||||
@@ -0,0 +1,190 @@
|
||||
/*
|
||||
* Copyright 2012-2023 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.boot.autoconfigure.aop;
|
||||
|
||||
import org.aspectj.lang.annotation.Aspect;
|
||||
import org.aspectj.lang.annotation.Before;
|
||||
import org.aspectj.weaver.Advice;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import org.springframework.aop.support.AopUtils;
|
||||
import org.springframework.boot.autoconfigure.AutoConfigurations;
|
||||
import org.springframework.boot.test.context.FilteredClassLoader;
|
||||
import org.springframework.boot.test.context.assertj.AssertableApplicationContext;
|
||||
import org.springframework.boot.test.context.runner.ApplicationContextRunner;
|
||||
import org.springframework.boot.test.context.runner.ContextConsumer;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.EnableAspectJAutoProxy;
|
||||
import org.springframework.context.annotation.Import;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.security.config.annotation.method.configuration.EnableMethodSecurity;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
/**
|
||||
* Tests for {@link AopAutoConfiguration}.
|
||||
*
|
||||
* @author Eberhard Wolff
|
||||
* @author Stephane Nicoll
|
||||
*/
|
||||
class AopAutoConfigurationTests {
|
||||
|
||||
private final ApplicationContextRunner contextRunner = new ApplicationContextRunner()
|
||||
.withConfiguration(AutoConfigurations.of(AopAutoConfiguration.class));
|
||||
|
||||
@Test
|
||||
void aopDisabled() {
|
||||
this.contextRunner.withUserConfiguration(TestConfiguration.class)
|
||||
.withPropertyValues("spring.aop.auto:false")
|
||||
.run((context) -> {
|
||||
TestAspect aspect = context.getBean(TestAspect.class);
|
||||
assertThat(aspect.isCalled()).isFalse();
|
||||
TestBean bean = context.getBean(TestBean.class);
|
||||
bean.foo();
|
||||
assertThat(aspect.isCalled()).isFalse();
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
void aopWithDefaultSettings() {
|
||||
this.contextRunner.withUserConfiguration(TestConfiguration.class).run(proxyTargetClassEnabled());
|
||||
}
|
||||
|
||||
@Test
|
||||
void aopWithEnabledProxyTargetClass() {
|
||||
this.contextRunner.withUserConfiguration(TestConfiguration.class)
|
||||
.withPropertyValues("spring.aop.proxy-target-class:true")
|
||||
.run(proxyTargetClassEnabled());
|
||||
}
|
||||
|
||||
@Test
|
||||
void aopWithDisabledProxyTargetClass() {
|
||||
this.contextRunner.withUserConfiguration(TestConfiguration.class)
|
||||
.withPropertyValues("spring.aop.proxy-target-class:false")
|
||||
.run(proxyTargetClassDisabled());
|
||||
}
|
||||
|
||||
@Test
|
||||
void customConfigurationWithProxyTargetClassDefaultDoesNotDisableProxying() {
|
||||
this.contextRunner.withUserConfiguration(CustomTestConfiguration.class).run(proxyTargetClassEnabled());
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
void whenGlobalMethodSecurityIsEnabledAndAspectJIsNotAvailableThenClassProxyingIsStillUsedByDefault() {
|
||||
this.contextRunner.withClassLoader(new FilteredClassLoader(Advice.class))
|
||||
.withUserConfiguration(ExampleController.class, EnableGlobalMethodSecurityConfiguration.class)
|
||||
.run((context) -> assertThat(context).getBean(ExampleController.class).matches(AopUtils::isCglibProxy));
|
||||
}
|
||||
|
||||
private ContextConsumer<AssertableApplicationContext> proxyTargetClassEnabled() {
|
||||
return (context) -> {
|
||||
TestAspect aspect = context.getBean(TestAspect.class);
|
||||
assertThat(aspect.isCalled()).isFalse();
|
||||
TestBean bean = context.getBean(TestBean.class);
|
||||
bean.foo();
|
||||
assertThat(aspect.isCalled()).isTrue();
|
||||
};
|
||||
}
|
||||
|
||||
private ContextConsumer<AssertableApplicationContext> proxyTargetClassDisabled() {
|
||||
return (context) -> {
|
||||
TestAspect aspect = context.getBean(TestAspect.class);
|
||||
assertThat(aspect.isCalled()).isFalse();
|
||||
TestInterface bean = context.getBean(TestInterface.class);
|
||||
bean.foo();
|
||||
assertThat(aspect.isCalled()).isTrue();
|
||||
assertThat(context).doesNotHaveBean(TestBean.class);
|
||||
};
|
||||
}
|
||||
|
||||
@EnableAspectJAutoProxy
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
@Import(TestConfiguration.class)
|
||||
static class CustomTestConfiguration {
|
||||
|
||||
}
|
||||
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
static class TestConfiguration {
|
||||
|
||||
@Bean
|
||||
TestAspect aspect() {
|
||||
return new TestAspect();
|
||||
}
|
||||
|
||||
@Bean
|
||||
TestInterface bean() {
|
||||
return new TestBean();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static class TestBean implements TestInterface {
|
||||
|
||||
@Override
|
||||
public void foo() {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Aspect
|
||||
static class TestAspect {
|
||||
|
||||
private boolean called;
|
||||
|
||||
boolean isCalled() {
|
||||
return this.called;
|
||||
}
|
||||
|
||||
@Before("execution(* foo(..))")
|
||||
void before() {
|
||||
this.called = true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
interface TestInterface {
|
||||
|
||||
void foo();
|
||||
|
||||
}
|
||||
|
||||
@EnableMethodSecurity(prePostEnabled = true)
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
static class EnableGlobalMethodSecurityConfiguration {
|
||||
|
||||
}
|
||||
|
||||
public static class ExampleController implements TestInterface {
|
||||
|
||||
@RequestMapping("/test")
|
||||
@PreAuthorize("true")
|
||||
String demo() {
|
||||
return "test";
|
||||
}
|
||||
|
||||
@Override
|
||||
public void foo() {
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
/*
|
||||
* Copyright 2012-2023 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.boot.autoconfigure.aop;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import org.springframework.aop.config.AopConfigUtils;
|
||||
import org.springframework.beans.factory.config.BeanDefinition;
|
||||
import org.springframework.boot.autoconfigure.AutoConfigurations;
|
||||
import org.springframework.boot.test.context.runner.ApplicationContextRunner;
|
||||
import org.springframework.boot.testsupport.classpath.ClassPathExclusions;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
/**
|
||||
* Tests for {@link AopAutoConfiguration} without AspectJ.
|
||||
*
|
||||
* @author Andy Wilkinson
|
||||
*/
|
||||
@ClassPathExclusions("aspectjweaver*.jar")
|
||||
class NonAspectJAopAutoConfigurationTests {
|
||||
|
||||
private final ApplicationContextRunner contextRunner = new ApplicationContextRunner()
|
||||
.withConfiguration(AutoConfigurations.of(AopAutoConfiguration.class));
|
||||
|
||||
@Test
|
||||
void whenAspectJIsAbsentAndProxyTargetClassIsEnabledProxyCreatorBeanIsDefined() {
|
||||
this.contextRunner.run((context) -> {
|
||||
BeanDefinition autoProxyCreator = context.getBeanFactory()
|
||||
.getBeanDefinition(AopConfigUtils.AUTO_PROXY_CREATOR_BEAN_NAME);
|
||||
assertThat(autoProxyCreator.getPropertyValues().get("proxyTargetClass")).isEqualTo(Boolean.TRUE);
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
void whenAspectJIsAbsentAndProxyTargetClassIsDisabledNoProxyCreatorBeanIsDefined() {
|
||||
this.contextRunner.withPropertyValues("spring.aop.proxy-target-class:false")
|
||||
.run((context) -> assertThat(context).doesNotHaveBean(AopConfigUtils.AUTO_PROXY_CREATOR_BEAN_NAME));
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user