嗨,我正在为AWS组件之间的消息传递构建一个库,所以我想要一个轻量级的解决方案。解决方案的一部分要求我在调用带注释的方法时监听,所以我想我会使用一个切入点并实现一个关于到达该切入点时该做什么的建议。
格拉德尔。生成脚本如下所示:
buildscript {
ext {
// some company-specific config here
nexus = {
credentials {
username nexusBuildUserToken
password nexusBuildPassToken
}
url nexusRepoURL
}
}
repositories {
mavenCentral()
maven(nexus)
}
dependencies {
classpath("net.researchgate:gradle-release:$gradleReleasePluginVersion")
classpath("gradle.plugin.aspectj:gradle-aspectj:$gradleAspectJPluginVersion")
}
}
apply plugin: 'java'
// IDE
apply plugin: 'idea'
apply plugin: 'eclipse-wtp'
apply plugin: "aspectj.gradle"
jar {
enabled = true
}
// project artifact info
group = groupId
archivesBaseName = artifactId
repositories {
mavenCentral()
maven(nexus)
maven {
url "https://dl.bintray.com/findify/maven"
}
}
dependencies {
compile("org.aspectj:aspectjtools:$aspectjVersion")
compile("org.apache.commons:commons-lang3:${commonsLang3Version}")
compile("com.fasterxml.jackson.dataformat:jackson-dataformat-yaml:${jacksonDataformatYamlVersion}")
compile("org.elasticmq:elasticmq-rest-sqs_2.11:0.14.1")
compile("com.amazonaws:aws-java-sdk-sqs:${awsMessagingVersion}")
compile("com.amazonaws:aws-java-sdk-sns:${awsMessagingVersion}")
compile("au.com.auspost:json-encryption:${jsonEncryptionVersion}")
compile("org.apache.commons:commons-lang3:${commonsLang3Version}")
compile("org.reflections:reflections:${reflectionsVersion}")
compile("redis.clients:jedis:${jedisVersion}")
compile("org.aspectj:aspectjweaver:$aspectjVersion")
compile("org.aspectj:aspectjrt:$aspectjVersion")
testCompile("junit:junit:${jUnitVersion}")
testCompile("org.mockito:mockito-core:${mockitoCoreVersion}")
testCompile("org.assertj:assertj-core:${assertjVersion}")
testCompile("ai.grakn:redis-mock:${embeddedRedisVersion}")
testCompile("org.slf4j:slf4j-simple:1.7.25")
testCompile("ch.qos.logback:logback-core:1.2.3")
testCompile(group: 'io.findify', name: 'sqsmock_2.11', version: '0.3.2')
}
正如你所见,我包括了所有aspectj库,以确保我没有遗漏任何我需要的东西(请随时告诉我我不需要的东西)。
我希望编织的课程是:
@Aspect
public class TopicSenderManager {
private ThreadPoolFactory threadPoolFactory;
private CorrelationService correlationService = new CorrelationService.Default();
private Map<String, TopicSenderProcessor> topicSenderProcessors = new HashMap<>();
private ExecutorService executor;
public TopicSenderManager(Map<String, TopicSenderProcessor> topicSenderProcessors) {
this.threadPoolFactory = new ThreadPoolFactory.Default();
this.topicSenderProcessors = topicSenderProcessors;
executor = threadPoolFactory.create(topicSenderProcessors.size(), "TopicSender");
}
@Around("@annotation(topicSender) && execution(* *(..))")
public Object sendMessageToTopic(ProceedingJoinPoint pjp, TopicSender topicSender) throws Throwable {
TopicSenderProcessor topicSenderProcessor = getProcessor(topicSender.topicAlias(), topicSender.eventType());
topicSenderProcessor.setCorrelationId(correlationService.read());
Object[] args = pjp.getArgs();
if (args == null || args.length != 1) {
throw new Exception("naughty, naughty");
} else {
topicSenderProcessor.setEventMessage((EventMessage) args[0]);
executor.execute(topicSenderProcessor);
}
return pjp.proceed();
}
public Map<String, TopicSenderProcessor> getTopicSenderProcessors() {
return topicSenderProcessors;
}
public TopicSenderProcessor getProcessor(String topic, String eventType) {
String senderKey = topic + "," + eventType;
return topicSenderProcessors.get(senderKey);
}
}
我希望这将完成的是提取一个用TopicSender注释的方法的每次执行(调用),并在线程池的一个线程中执行相关的处理器。
我查看了TopicSenderManager的反编译类,如下所示:
@Aspect
public class TopicSenderManager {
private ThreadPoolFactory threadPoolFactory = new Default();
private CorrelationService correlationService = new au.com.auspost.messaging.CorrelationService.Default();
private Map<String, TopicSenderProcessor> topicSenderProcessors = new HashMap();
private ExecutorService executor;
public TopicSenderManager(Map<String, TopicSenderProcessor> topicSenderProcessors) {
this.topicSenderProcessors = topicSenderProcessors;
this.executor = this.threadPoolFactory.create(topicSenderProcessors.size(), "TopicSender");
}
@Around("@annotation(topicSender) && execution(* *(..))")
public Object sendMessageToTopic(ProceedingJoinPoint pjp, TopicSender topicSender) throws Throwable {
TopicSenderProcessor topicSenderProcessor = this.getProcessor(topicSender.topicAlias(), topicSender.eventType());
topicSenderProcessor.setCorrelationId(ajc$inlineAccessFieldGet$au_com_auspost_messaging_send_topic_TopicSenderManager$au_com_auspost_messaging_send_topic_TopicSenderManager$correlationService(this).read());
Object[] args = pjp.getArgs();
if (args != null && args.length == 1) {
topicSenderProcessor.setEventMessage((EventMessage)args[0]);
ajc$inlineAccessFieldGet$au_com_auspost_messaging_send_topic_TopicSenderManager$au_com_auspost_messaging_send_topic_TopicSenderManager$executor(this).execute(topicSenderProcessor);
return pjp.proceed();
} else {
throw new Exception("naughty, naughty");
}
}
public Map<String, TopicSenderProcessor> getTopicSenderProcessors() {
return this.topicSenderProcessors;
}
public TopicSenderProcessor getProcessor(String topic, String eventType) {
String senderKey = topic + "," + eventType;
return (TopicSenderProcessor)this.topicSenderProcessors.get(senderKey);
}
public static TopicSenderManager aspectOf() {
if (ajc$perSingletonInstance == null) {
throw new NoAspectBoundException("au.com.auspost.messaging.send.topic.TopicSenderManager", ajc$initFailureCause);
} else {
return ajc$perSingletonInstance;
}
}
public static boolean hasAspect() {
return ajc$perSingletonInstance != null;
}
static {
try {
ajc$postClinit();
} catch (Throwable var1) {
ajc$initFailureCause = var1;
}
}
}
我想这就是应该发生的编织。
下一件事是建立一个(某种)单元测试来演示我想要的行为:
首先,我定义了一个我想要截取的方法的简单示例:
public class SenderT1E1 {
@TopicSender(topicAlias = "t1", eventType = "a.c.a.e1")
public void aSendingMethod(EventMessage<TestMessage> eventMessage) {
// do what you like before sending the message
}
}
然后看它的测试:
public class SenderE1T1Test {
static TopicSenderManager manager;
@BeforeClass
public static void setUp() throws Exception {
MockAmazonClient snsClient = new MockAmazonClient();
TopicSenderFactory senderFactory = new TopicSenderFactory();
PublishResult publishResult = new PublishResult().withMessageId("E1T1");
manager = senderFactory.make(snsClient.amazonSNS(publishResult), "aws-send-test.properties");
}
@Test
public void whenSenderIsCalledMessageIsSent() {
SenderT1E1 target = new SenderT1E1();
EventMessage message = new EventMessage<>();
message.setEventType("a.c.a.e1");
message.setPayload(new TestMessage());
target.aSendingMethod(message);
TopicSenderProcessor processor = manager.getProcessor("http://localhost:8001/topic/t1", "a.c.a.e1");
assertThat(manager.getTopicSenderProcessors().entrySet().size(), is(2));
manager.getTopicSenderProcessors().forEach((k,v) -> System.out.println(k + ", " + v));
assertThat(processor, is(notNullValue()));
// now, did it execute...
assertThat(processor.getEventMessage(), is(notNullValue()));
assertThat(processor.getLastPublishRequest(), is(notNullValue()));
assertThat(processor.getLastPublishResult(), is(notNullValue()));
}
}
基本上,到〈code〉//的所有内容现在都执行了 行可以工作,但之后所有内容都为空。所以看起来似乎永远都达不到切入点。
那么,编织工作不正常吗?@周围
规范中的切入点和建议不正确吗?是否有某种运行时触发器,我已经忘记了?还是别的什么?
我想我应该在这里声明一下:我不使用spring的原因是我发现依赖项的数量导致了一个非常臃肿的库,我正在尽可能地精简它。我想要aspectJ的速度优势,我更喜欢编译时编织,因为这是一个用于应用程序的库,如果有必要,我会求助于spring,但这确实是最后的选择。
这个问题属于其他类别。没有触发切入点的原因是我在使用编译时编织,而编织的目标类在运行时不在类路径中。编织的目标类在src/test/java中,而切入点在src/main/java中,当编译应用程序时,src/test/java是不可见的。我需要的是运行时编织,这样可以发现并编织测试类,然后切入点就可以工作了。不幸的是,运行时编织是一个昂贵的操作,所以对我来说不是一个选项,所以我转而使用侦听器模式。从实现者的角度来看,它没有那么干净,但在性能方面要好得多
下面是我的代码片段: 服务我mpl.java 现在,我想要的是每当从方法worker(请求,字符串id)抛出null点异常时,我想要执行一些特定的任务,如上图所示。为此,我编写了一个方面类,如下所示: 我的方面。Java语言 电流输出: 期望输出: 如您所见,没有被触发,因此没有打印值。这是什么原因? 注: > 还尝试更改方法的名称,以消除任何也不起作用的重载问题。 到目前为止,尝试了各种其他切入
我想实现重试功能(当消费者出现问题时)3次,然后消息应该转到另一个队列(死信交换)。我已按如下方式配置队列/交换 常规邮件交换名称:test\u exchange邮件队列:test\u queue test\u queue绑定到具有路由密钥的test\u exchange test\u queue 死信交换名称:test_dlq_exchange死消息队列:test_dlq_queuetest_d
我已经从github克隆了一个项目,在使用Thread添加包并运行之后,节点只显示一个警告: 以下软件包使用不建议使用的“rnpm”配置,该配置将从下一个版本开始停止工作 该节点立即关闭(在照片中)并且立即关闭。
我有以下QueryDSL查询: 它使用计数,因为这是Spring数据用来对结果进行分页的第一个查询。
在Spring中将一个方面配置为: 是: } 如果我使用注释实现方法,正在按预期工作。但是如果注释在接口上,它就不起作用。这是正常行为还是我做错了什么?
我想在Eclipse(Oxygen 4.7.1a)中使用JUnit 5创建一个JUnit测试。这个JUnit测试应该在一个名为test的独立src文件夹中。但是,由于我是JUnit和Java9的新手,我遇到了以下问题。 我不想为此使用像Gradle或Maven这样构建工具。 因为我有两个不同的src文件夹,一个用于项目src,另一个用于测试用例: 我需要两个module-info.java文件吗?