我在最近编辑后今天才发现这个老问题。
你想要的是一个基于pertypewithin
. 虽然这个想法很好,但存在一个技术问题:您不能从around() : execution(*.new(..))
通知中返回对象,因为所讨论的对象尚未完全实例化,并且周围通知隐式返回void
。自己尝试并将建议返回类型更改为void
并且不返回任何内容。它有效 - 惊喜,惊喜!;-)
那么你能做什么呢?改为使用around() : call(*.new(..))
以操作构造函数调用的结果。您甚至可以通过不proceed()
从那里调用来完全跳过对象创建。
有几种方法可以利用它来使您的资源对象缓存为单例。但是因为您特别要求一个pertypewithin
用例,所以我将选择一个涉及这种方面实例化的解决方案。这里的缺点是您需要结合两个方面才能达到预期的结果。
示例资源类:
package de.scrum_master.resource;
public class Foo {}
package de.scrum_master.resource;
public class Bar {}
驱动程序应用程序创建每种资源类型的多个实例:
package de.scrum_master.app;
import de.scrum_master.resource.Bar;
import de.scrum_master.resource.Foo;
public class Application {
public static void main(String[] args) {
System.out.println(new Foo());
System.out.println(new Foo());
System.out.println(new Bar());
System.out.println(new Bar());
}
}
资源池方面的修改版本:
package de.scrum_master.resourceManager;
public aspect ResourcePool pertypewithin(de.scrum_master.resource..*) {
private Object cached;
after(Object instance) : execution(*.new(..)) && this(instance) {
// Not necessary because SingletonAspect only proceeds for 'cache == null'
//if (cached != null) return;
cached = instance;
System.out.println("Cached instance = " + cached);
}
public Object getCachedInstance() {
return cached;
}
}
方面跳过对象创建对象并返回缓存对象:
package de.scrum_master.resourceManager;
public aspect SingletonAspect {
Object around() : call(de.scrum_master.resource..*.new(..)) {
Object cached = ResourcePool
.aspectOf(thisJoinPointStaticPart.getSignature().getDeclaringType())
.getCachedInstance();
return cached == null ? proceed() : cached;
}
}
控制台日志:
Cached instance = de.scrum_master.resource.Foo@5caf905d
de.scrum_master.resource.Foo@5caf905d
de.scrum_master.resource.Foo@5caf905d
Cached instance = de.scrum_master.resource.Bar@8efb846
de.scrum_master.resource.Bar@8efb846
de.scrum_master.resource.Bar@8efb846