Est-il possible d'avoir une instance d'aspect par pointcut? Je veux mettre en œuvre un aspect simple basé sur un proxy Spring AOP. Si la méthode marquée dans des classes distinctes, à la fois perthis et pertarget fonctionne très bien. Mais que puis-je faire lorsque plusieurs méthodes doivent être mises en cache dans une classe?Printemps AOP et Aspect "perthis"
Exemple de projet: https://github.com/mezlogo/spring-aop-sample
Par exemple, j'ai:
build.gradle
buildscript {
repositories { jcenter() }
dependencies {
classpath("org.springframework.boot:spring-boot-gradle-plugin:1.3.5.RELEASE")
}
}
apply plugin: 'spring-boot'
apply plugin: 'groovy'
repositories { jcenter() }
dependencies {
compile group: 'org.codehaus.groovy', name: 'groovy-all', version: '2.4.6'
compile 'org.springframework.boot:spring-boot-starter-aop'
testCompile 'org.springframework.boot:spring-boot-starter-test'
testCompile group: 'org.spockframework', name: 'spock-spring', version: '1.0-groovy-2.4'
}
CacheAspect.groovy
package mezlogo
import groovy.transform.CompileStatic
import org.aspectj.lang.ProceedingJoinPoint
import org.aspectj.lang.annotation.Around
import org.aspectj.lang.annotation.Aspect
@CompileStatic
@Aspect("perthis(@annotation(mezlogo.CacheIt))")
class CacheAspect {
int cachedValue = -1
@Around('@annotation(mezlogo.CacheIt)')
int cacheRemoteService(ProceedingJoinPoint pjp) {
if (-1 == cachedValue) {
def result = pjp.proceed()
cachedValue = (int) result
}
cachedValue
}
}
sur mesure CacheIt.java annotation
package mezlogo;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface CacheIt{}
Config.groovy
package mezlogo
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration
import org.springframework.context.annotation.EnableAspectJAutoProxy
import org.springframework.context.annotation.Scope
@Configuration
@EnableAspectJAutoProxy
class Config {
@Bean
RemoteService remoteService() { new RemoteService() }
@Bean
@Scope("prototype")
CacheAspect cacheAspect() { new CacheAspect() }
}
RemoteService.groovy
package mezlogo
import groovy.transform.CompileStatic
@CompileStatic
class RemoteService {
static final int RESULT = 1
static final int ANOTHER_RESULT = 2
static final RuntimeException exception = new RuntimeException('Prevent it by caching')
boolean isFirstAccessed = true
boolean isSecondAccessed = true
@CacheIt
int firstMethod() {
if (!isFirstAccessed) { throw exception }
isFirstAccessed = false
RESULT
}
@CacheIt
int secondMethod() {
if (!isSecondAccessed) { throw exception }
isSecondAccessed = false
ANOTHER_RESULT
}
}
Enfin, CacheAspectSpec.groovy
package mezlogo
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.boot.test.SpringApplicationConfiguration
import spock.lang.Specification
import spock.lang.Stepwise
@SpringApplicationConfiguration(Config)
@Stepwise
class CacheAspectSpec extends Specification {
@Autowired
RemoteService sut
def "should cache firstMethod result"() {
expect: "firstMethod return correct result"
sut.firstMethod() == RemoteService.RESULT
when: "firstMethod fired again"
sut.firstMethod()
then: "no RTE has been thrown"
noExceptionThrown()
}
def "should cache secondMethod result"() {
expect: "secondMethod return correct result"
//Cache return RemoteService.RESULT value
sut.secondMethod() == RemoteService.ANOTHER_RESULT
when: "secondMethod fired again"
sut.secondMethod()
then: "no RTE has been thrown"
noExceptionThrown()
}
}
La réponse courte serait Non vous ne pouvez pas. Le prolongé serait la réponse du consultant et cela dépendrait. Vous ne pouvez pas avoir cela avec Spring AOP car cela est basé sur un proxy et ne fonctionnera tout simplement pas avec cela (il ne supporte qu'un ensemble limité du langage AspectJ). Vous devriez utiliser l'Aspectj natif et utiliser le tissage de temps de compilation (peut-être que le tissage de charge fonctionnerait aussi bien), vous aurez donc besoin d'une solution AspectJ complète et non d'une solution proxy (par défaut Spring AOP). –
vous devez ajouter des balises correctes – emotionlessbananas