好的,因此我需要将一些CDI拦截器迁移到Spring Boot,并且我编写了一个简单的“概念验证”测试用例:
package ch.cypherk.myapp.util.aop
import org.aspectj.lang.JoinPoint
import org.aspectj.lang.annotation.Aspect
import org.aspectj.lang.annotation.Before
import org.assertj.core.api.Assertions.assertThat
import org.junit.Test
import org.junit.runner.RunWith
import org.springframework.boot.test.context.SpringBootTest
import org.springframework.context.annotation.Configuration
import org.springframework.context.annotation.EnableAspectJAutoProxy
import org.springframework.stereotype.Component
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner
import javax.inject.Inject
@RunWith(SpringJUnit4ClassRunner::class)
@SpringBootTest
class SimpleInterceptorIT{
companion object {
val expectedArg = "Hakuna Matata"
lateinit var interceptorOutput:String
}
@Inject
private lateinit var client:ClientClass
@Test
fun `interceptor works`(){
client.foo()
assertThat(interceptorOutput).isEqualTo("ch.cypherk.myapp.util.aop.TargetClass.foo(\"$expectedArg\")")
}
}
@Component
class TargetClass{
fun foo(arg:String){
println("I did something.")
}
}
@Component
class ClientClass(val target:TargetClass){
fun foo(){
target.foo("Hakuna Matata")
}
}
@Aspect
@Configuration
@EnableAspectJAutoProxy
class TestInterceptorConfiguration{
@Before("execution(* ch.cypherk.myapp.util.aop.TargetClass.*(..))")
fun intercept(joinPoint:JoinPoint){
val signature = joinPoint.signature
println(signature)
SimpleInterceptorIT.interceptorOutput =
"${signature.declaringTypeName}.${signature.name}(${
joinPoint.args
.map { when(it){
is String -> "\"$it\""
else -> it
}}
.joinToString(",")
})"
}
}
这些是该软件包中的 ONLY 类。
输出:
void ch.cypherk.myapp.util.aop.TargetClass.foo(String)
I did something.
测试是绿色的。
现在让我们扩大搜索范围...
@Aspect
@Configuration
@EnableAspectJAutoProxy
class TestInterceptorConfiguration{
@Before("execution(* ch.cypherk.myapp.util.aop.*.*(..))")
fun intercept(joinPoint:JoinPoint){
val signature = joinPoint.signature
println(signature)
SimpleInterceptorIT.interceptorOutput =
"${signature.declaringTypeName}.${signature.name}(${
joinPoint.args
.map { when(it){
is String -> "\"$it\""
else -> it
}}
.joinToString(",")
})"
}
}
这需要 ETERNITY 来开始。
是的,输出为
void ch.cypherk.myapp.util.aop.ClientClass.foo()
void ch.cypherk.myapp.util.aop.TargetClass.foo(String)
I did something.
是的,测试是绿色的。
是的,测试运行的时间仅为117ms
。
但是Spring需要花很长时间才能启动。
为什么?更重要的是,我该怎么办?因为这不是很好。
我看过spring-boot-starter-aop
并定义了
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
<version>2.1.4.RELEASE</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
<version>5.1.6.RELEASE</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.9.2</version>
<scope>compile</scope>
</dependency>
</dependencies>
所有这些-正如您将注意到的-编译限定范围。
那么,我的期望是,所有这些都将在编译时被编织。 似乎并非如此。否则,它不会阻止Spring对程序包做任何奇怪的事情。
在这里,我希望能帮助您了解正在发生的事情。
答案 0 :(得分:1)
我做的和你做的一样,而且运行很快。
但是我有不同的依赖性。
你可以尝试
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<scope>compile</scope>
</dependency>
编辑:
我已经运行了您提供的Kotlin代码,输出为:
. ____ _ __ _ _
/\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
\\/ ___)| |_)| | | | | || (_| | ) ) ) )
' |____| .__|_| |_|_| |_\__, | / / / /
=========|_|==============|___/=/_/_/_/
:: Spring Boot :: (v2.1.5.RELEASE)
2019-06-04 17:05:19.411 INFO 19840 --- [ main] c.c.myapp.util.aop.SimpleInterceptorIT : Starting SimpleInterceptorIT on LAPTOP-FQPHQ5E5 with PID 19840 (started by simon in C:\Users\simon\Workspace\stackoverflow\demo-aop-kotlin)
2019-06-04 17:05:19.411 INFO 19840 --- [ main] c.c.myapp.util.aop.SimpleInterceptorIT : No active profile set, falling back to default profiles: default
2019-06-04 17:05:21.353 INFO 19840 --- [ main] c.c.myapp.util.aop.SimpleInterceptorIT : Started SimpleInterceptorIT in 2.358 seconds (JVM running for 4.008)
void ch.cypherk.myapp.util.aop.ClientClass.foo()
void ch.cypherk.myapp.util.aop.TargetClass.foo(String)
I did something.
两次执行之间没有区别。
答案 1 :(得分:1)
我不确定,但是我如何理解Aspectjweaver,在加载时向Java类介绍建议
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.9.2</version>
</dependency>
编译时编织是最简单的方法
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>aspectj-maven-plugin</artifactId>
<version>1.7</version>
<configuration>
<complianceLevel>1.8</complianceLevel>
<source>1.8</source>
<target>1.8</target>
<showWeaveInfo>true</showWeaveInfo>
<verbose>true</verbose>
<Xlint>ignore</Xlint>
<encoding>UTF-8 </encoding>
</configuration>
<executions>
<execution>
<goals>
<!-- use this goal to weave all your main classes -->
<goal>compile</goal>
<!-- use this goal to weave all your test classes -->
<goal>test-compile</goal>
</goals>
</execution>
</executions>
</plugin>
Havent尝试了一下,但希望对您有用。