构造函数对象上的AspectJ切入点 [英] AspectJ pointcut on constructor object

查看:214
本文介绍了构造函数对象上的AspectJ切入点的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我需要使用AspectJ为每个初始化对象注入几个方法。

I need to inject few methods to every initialized object using AspectJ.

我想用这个:

pointcut vistaInjection(Object o)
    : initialization(java.lang.Object.new() ) 
    && target(o)
    && !within(objectAspect);

before(Object o): methodInjection(o){System.err.println("INIT");}

切入对象的初始化,因此我可以将这些方法直接注入到作为其他对象一部分的对象中。

to pointcut initialization of object, so I can inject these methods directly into the object that is part of every other object.

然而,它不起作用。你知道为什么吗?或者可能是另一种方式如何100%确定每个初始化对象都将被切入点? * .new不适用于字符串,列表和其他内容。

However, it does't work. Do you have any idea why? Or what may be an other way how to make 100% sure that every single initialized object will be pointcut? *.new does not work for stuff such String, Lists and others.

谢谢!

推荐答案

用户selig是对的:你可能不想拦截所有对象创建,尤其不是JDK / JRE类中的那些。但是对于它的价值,这里有一个解释什么有用,什么有用,有什么不可用:

User selig is right: You probably do not want to intercept all object creations, especially not those in JDK/JRE classes. But for what it is worth, here is an explanation of what works and how and what not:

一个小驱动程序应用程序:

public class Application {
    public static void main(String[] args) {
        new Application();
        new String();
    }
}

具有不同类型构造函数的方面 - 相关的切入点/建议:

public aspect ObjectCreationAspect {
    before() : preinitialization(*.new(..)) && !within(ObjectCreationAspect) {
        System.out.println(thisJoinPointStaticPart);
    }

    before() : initialization(*.new(..)) && !within(ObjectCreationAspect) {
        System.out.println(thisJoinPointStaticPart);
    }

    before() : call(*.new(..)) && !within(ObjectCreationAspect) {
        System.out.println(thisJoinPointStaticPart);
    }

    before() : execution(*.new(..)) && !within(ObjectCreationAspect) {
        System.out.println(thisJoinPointStaticPart);
    }
}

编织驱动程序应用程序的输出:

call(Application())
preinitialization(Application())
initialization(Application())
execution(Application())
call(java.lang.String())

说明:

AspectJ中有不同类型的编织:

There are different types of weaving in AspectJ:


  • 编译时编织(CTW):只能编织由 ajc (AspectJ编译器)编译的类。这不包括JDK / JRE类以及您不从源代码编译的第三方库。上面的示例输出显示了编译时编织的效果。

  • 二进制编织(BW):AspectJ编译器用于将方面代码直接编译为现有字节代码。这适用于您自己的预编译应用程序类以及第三方库。从理论上讲,如果将 rt.jar 放在AspectJ编译器的路径中,它也适用于JDK / JRE类。 JDK / JRE编织有点棘手,但我之前已经完成了。您可以生成 rt.jar 的新编织版本,或者只是一个带有一些编织JDK类的小JAR文件,然后在启动应用程序时将其添加到JDK / JRE的引导类路径中。

  • 加载时间编织(LTW):基本上这是BW,但在类加载期间动态完成。在这个AspectJ场景中,您只能在一个方面编织器的影响下编织由类加载器加载的类。因此,它适用于您自己的代码和第三方库,但通常不使用在加载方面编织器之前加载的JDK / JRE引导类。这是一个鸡蛋和蛋类型的问题:编织者需要JRE在它可以加载之前运行,但是为了编织JRE类,编织器必须在那些类被引导之前存在。

  • Compile-time weaving (CTW): Only classes which are compiled by ajc (AspectJ compiler) can be woven. This excludes JDK/JRE classes and also 3rd party libraries which you do not compile from source. the sample output from above shows the effect of compile-time weaving.
  • Binary weaving (BW): The AspectJ compiler is used to compile aspect code directly into existing byte code. This works with your own precompiled application classes as well as with 3rd party libraries. Theoretically it also works with JDK/JRE classes if you put rt.jar on the AspectJ compiler's in-path. JDK/JRE weaving is a bit tricky, but I have done it before. You can produce a newly woven version of rt.jar or just a small JAR file with a few woven JDK classes which then you prepend to the boot-classpath of the JDK/JRE when firing up your application.
  • Load-time weaving (LTW): Basically this is BW, but done dynamically during class-loading. In this AspectJ scenario you can only weave classes which are loaded by a classloader under the influence of an aspect weaver. Thus, it works with you own code and 3rd party libraries, but usually not with JDK/JRE bootstrapping classes which are loaded before the aspect weaver is loaded. It is a hen-and-egg type of problem: The weaver needs the JRE to be running before it can be loaded, but in order to weave JRE classes the weaver would have to be there before those classes are bootstrapped.

现在您可以轻松地从您自己的代码或编织的第三方代码拦截调用到JDK / JRE构造函数,你可以在日志输出行看到 call(java.lang.String())。但是你不能拦截从JRE类到JRE类的内部调用。

Now what you can easily do is intercept calls to JDK/JRE constructors from your own code oder woven 3rd party code, as you can see in the log output line saying call(java.lang.String()). You cannot intercept internal calls from JRE class to JRE class though.

说了这么多我真的很想知道你想做什么样的可怕事情。我的意思是,你解释它,这听起来像一个巨大的设计错误。或者你想重新发明轮子并编写一些已经存在的探查器或调试器。你期望拦截每个单个对象创建什么?如果只记录您正在记录的字符串,它会极大地降低您的应用程序速度,大幅增加内存消耗并创建更多对象。请重新考虑并尝试思考你真正想做的事情。也许那时我们可以建议一种实现目标的聪明方法。

Having said all that I really wonder what kind of horrible thing you want to do. I mean, you explain it and it sounds like a tremendous design error. Or you want to re-invent the wheel and write some kind of profiler or debugger which already exists. What do you expect from intercepting each single object creation? It would tremendously slow down your application, drastically increase memory consumption and create even more objects, if only the strings you are logging. Please reconsider and try to think about what you really want to do. Maybe then we can suggest a smart way of achieving your goal.

这篇关于构造函数对象上的AspectJ切入点的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆