Java AspectJ:使用方法引用时拦截构造函数

Java AspectJ:使用方法引用时拦截构造函数,java,java-8,aspectj,Java,Java 8,Aspectj,对于使用new的正常构造函数调用,我使用 pointcut replaceableNew() : call((@Replaceable *).new(..)); Object around() : replaceableNew() { Constructor<?> constructor = ((ConstructorSignature) thisJoinPointStaticPart.getSignature()).getConstructor ;

对于使用
new
的正常构造函数调用,我使用

pointcut replaceableNew() : call((@Replaceable *).new(..));

Object around() : replaceableNew() {
        Constructor<?> constructor = ((ConstructorSignature) thisJoinPointStaticPart.getSignature()).getConstructor ;
        Class<?> declaringClass = constructor.getDeclaringClass(); 
        if (!Registry.getInstance().isReplaced(declaringClass))  {
            return proceed() ;
        }
        Class<?>[] parameterTypes = constructor.getParameterTypes();
        Object[] args = thisJoinPoint.getArgs();
        return Registry.getInstance().create(declaringClass, parameterTypes, args); // creates some sub-class of declaring class
    }
pointcut replacablenew():调用(@replacement*).new(..);
对象周围():replacablenew(){
构造函数=((构造函数签名)thisJoinPointStaticPart.getSignature()).getConstructor;
类declaringClass=构造函数。getDeclaringClass();
如果(!Registry.getInstance().isReplaced(declaringClass)){
返回继续();
}
类[]parameterTypes=constructor.getParameterTypes();
Object[]args=thisJoinPoint.getArgs();
return Registry.getInstance().create(declaringClass,parameterTypes,args);//创建声明类的一些子类
}
但当构造函数作为方法引用传递时,这不起作用

Stream.of(1,2).map(somereplacement::new).

实例方法引用(带“*lambda*”)的变通方法不起作用

执行((@replacement*)。新建(..)
切入点不允许替换返回的对象

也许上面的
调用(**(…)
执行(…
的组合可以工作,但这样我们会建议太多调用,也会创建和丢弃不必要的可替换实例。看起来很难看

还有其他想法吗

也许上面的
调用(**(..)
执行(..)
的一些组合可以工作

不,它不会,因为在使用方法引用时,AspectJ根本没有要拦截的
call()
joinpoint。反射构造函数调用也是如此

因此,您的想法只适用于简单的情况,即当存在可以拦截的普通构造函数调用时。正如您已经注意到的,您不能直接替换构造函数生成的实例,即使是低级别字节码工程框架(如ASM或BCEL)或更高级别的框架(如Javassist或ByteBuddy),也不能se JVM不允许这样做。使用这样的框架,您能做的最好的事情就是转换构造函数代码,使其跳过对象初始化,并使用伪参数直接调用超级构造函数(顺便说一句,为了跳过初始化,还必须检测所有超级构造函数)

此外,您的方面,即使可以替换由
执行(*.new(..)
返回的对象,也必须注意排除
this()
super()
调用,如果正在实例化注释类的子类,请确保做正确的事情

整个想法都不起作用。很抱歉破坏了你的梦想(我很多年前也有这个想法),但这些都是事实


回到问题:我再次要求你描述你想要实现什么,而不是描述你认为技术上应该如何实现。你的用例是什么?你想解决什么问题?

这是一个有趣的问题,但为了回答它,我必须创建我自己的应用程序用于测试和想象注册中心做什么的类,或者你提供我可以复制、编译、运行和分析的东西。它被称为an。我认为我对你的代码做什么有一个很好的想法,但实际上我并不想编写所有的代码来让你的方面工作和问题重现。所以请帮助我帮助你。比k你们。为了避免这又是一个例子,我也恳请你们不仅要解释你们想如何解决你们的问题,还要解释你们试图实现什么。这是你们正在开发的某种测试模拟工具吗?但这对最终的类不起作用。这不是模拟工具。这是一种定制一些标准的方法通过注入不同的类实现(主要是一些数据模型)生成的产品。它可以正常工作很多年,但不是在这种情况下。理论上,AspectJ可以通过调整调用lambda工厂的
invokedynamic
指令来支持方法引用的替换,该指令使用synthentic静态方法替换构造函数引用类似的签名。在synthentic方法中,它可能只调用引用的构造函数-然后
调用
切入点就可以工作。但是ApsectJ仍然不支持这一点。这对我们的框架来说不是致命的-我们可以在代码分析器中捕获这种情况并发出警告,ctr引用不能用于此类类。对不起,我的(正确)答案不是解释AspectJ在理论上能做什么,而是解释它在实践中能做什么。所以请接受这个答案,尽管你不喜欢现实。顺便说一句,就在昨天,AspectJ用户邮件列表上发布了一条消息,最终他们将主存储库从Eclipse的某个Git存储库移到了GitHub(直到昨天还只是一面镜子)和GitHub的票证问题。因此,现在比以前更容易提供PRs或创建问题。也许这值得先问一下ML,然后再问一个问题,如果维护人员同意的话。