Понимание ресурсов перехватчика Spring AOP - PullRequest
0 голосов
/ 04 июня 2019

Хорошо, поэтому мне нужно перенести некоторые CDI Interceptors на 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(",")
            })"
    }
}

Это ТОЛЬКО классы в этом пакете.

Выход:

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(",")
            })"
    }
}

Для запуска требуется ВЕЧНОСТЬ .

Да, вывод

void ch.cypherk.myapp.util.aop.ClientClass.foo()
void ch.cypherk.myapp.util.aop.TargetClass.foo(String)
I did something.

Да, тест зеленый.

Да, тест запускает всего за 117ms.

НО для запуска весны требуется вечность.

Почему? И что еще более важно, что я могу с этим поделать? Потому что это очень не хорошо.

Я посмотрел на 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>

Все это - как вы заметили - compile scoped.

Тогда я ожидал, что все это будет сплетено во время компиляции. Кажется, это не так. Или, если это так, это не мешает Spring делать что-то странное с пакетом.

Буду признателен за помощь в понимании происходящего здесь.

Ответы [ 2 ]

1 голос
/ 04 июня 2019

Я не уверен, но как я понимаю аспектjweaver, ознакомьтесь с классом 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>

Не пробовал, но надеюсь, что это работает для вас.

1 голос
/ 04 июня 2019

Я сделал то же самое, что и вы, и все работает быстро.

Но у меня разные зависимости.

Можете ли вы попробовать с

    <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>

Edit:

Я запустил предоставленный вами код 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.

Нет разницы между обоими казнями.

...