AspectJ

时间:2015-05-23 13:20:11

标签: java aspectj

注意:这是概念实施的证明,而不是最终的。

我有第3名。派对添加,我想限制他们的声音使用,例如限制持续时间等(安全管理员不可能)。为了实现这一点,我考虑用包装器替换AudioSystem.getLine()的返回。 这是测试方面:

@Aspect
public class MixerAspect {
    @Around("execution(* javax.sound.sampled.AudioSystem.getLine(javax.sound.sampled.Line.Info))")
    public Object getLineAdvice(ProceedingJoinPoint pjp) throws Throwable {
        System.out.println("AspectJ");
        pjp.getArgs();
        Line ret = (Line) pjp.proceed();
        return ret;
    }
}

每个附加组件都有自己的类加载器,它们通常不共享对象,所以这就是我想出的:

@Override
public Class<?> loadClass(String className) throws ClassNotFoundException {
....
if (className.equals(AudioSystem.class.getName())) {
    .....
    byte[] array = buffer.toByteArray();
        try {
            if (mixed == null)
                mixed = weaver.defineClass(className, array, new CodeSource(mixerAspect, (CodeSigner[]) null));
            return mixed;
        } catch (IOException e) {
            throw new ClassNotFoundException("unable to define class", e);
        }

这是WeavingURLClassloader的初始化代码:

weaver = new WeavingURLClassLoaderHelper(new URL[0], parent);
weaver.addURL(aspects[0]);

parent是可以访问Mixer方面的类加载器,而aspect是一个url-array,只有一个元素是指向MixerAspect所在目录的元素。 我的aop.xml:

<aspectj>
    <aspects>
        <aspect name="org.intellimate.izou.security.replaced.MixerAspect"/>
    </aspects>

    <weaver options="-Xset:weaveJavaxPackages=true -verbose -showWeaveInfo -debug">
        <!-- Weave types that are within the javax.* or org.aspectj.*
             packages. Also weave all types in the foo package that do
             not have the @NoWeave annotation. -->
        <include within="javax.*"/>
        <include within="org.intellimate.izou.security.replaced.*"/>
        <include within="javax.sound.sampled.AudioSystem"/>
    </weaver>
</aspectj>

这是(相关)日志:

....(no relevant log)
TraceFactory.instance=org.aspectj.weaver.tools.Jdk14TraceFactory@53aad5d5
[WeavingURLClassLoaderHelper] info AspectJ Weaver Version 1.8.5 built on Thursday Jan 29, 2015 at 01:03:58 GMT
[WeavingURLClassLoaderHelper] info register classloader ro.fortsoft.pf4j.IzouPluginClassLoader$WeavingURLClassLoaderHelper
[WeavingURLClassLoaderHelper] info using configuration /Users/LeanderK/IdeaProjects/Izou/target/classes/META-INF/aop.xml
[WeavingURLClassLoaderHelper] info register aspect org.intellimate.izou.security.replaced.MixerAspect
[WeavingURLClassLoaderHelper] info AspectJ Weaver Version 1.8.5 built on Thursday Jan 29, 2015 at 01:03:58 GMT
[WeavingURLClassLoaderHelper] info register classloader ro.fortsoft.pf4j.IzouPluginClassLoader$WeavingURLClassLoaderHelper
[WeavingURLClassLoaderHelper] info using configuration /Users/LeanderK/IdeaProjects/Izou/target/classes/META-INF/aop.xml
[WeavingURLClassLoaderHelper] info register aspect org.intellimate.izou.security.replaced.MixerAspect
...(no relevant log)
[WeavingURLClassLoaderHelper] debug weaving 'javax.sound.sampled.AudioSystem'
[WeavingURLClassLoaderHelper] weaveinfo Join point 'method-execution(javax.sound.sampled.Line javax.sound.sampled.AudioSystem.getLine(javax.sound.sampled.Line$Info))' in Type 'javax.sound.sampled.AudioSystem' (AudioSystem.java:410) advised by around advice from 'org.intellimate.izou.security.replaced.MixerAspect' (MixerAspect.class(from MixerAspect.java))
[WeavingURLClassLoaderHelper] debug generating class 'javax.sound.sampled.AudioSystem$AjcClosure1'
2015-05-24 20:12:13,945 FATAL [Thread-5] org.intellimate.izou.threadpool.ThreadPoolManager (ThreadPoolManager.java:59) - unable to provide callback for: org.intellimate.izou.addon.AddOnManager$$Lambda$19/970865974@1f4f3b69
java.util.concurrent.CompletionException: java.lang.NoSuchMethodError: org.intellimate.izou.security.replaced.MixerAspect.aspectOf()Lorg/intellimate/izou/security/replaced/MixerAspect;
    at java.util.concurrent.CompletableFuture.internalComplete(CompletableFuture.java:205) [?:1.8.0_25]
    at java.util.concurrent.CompletableFuture$AsyncRun.exec(CompletableFuture.java:459) [?:1.8.0_25]
    at java.util.concurrent.CompletableFuture$Async.run(CompletableFuture.java:428) [?:1.8.0_25]
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) [?:1.8.0_25]
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) [?:1.8.0_25]
    at org.intellimate.izou.threadpool.ThreadPoolManager$LoggingThreadFactory$1.run(ThreadPoolManager.java:73) [classes/:?]
Caused by: java.lang.NoSuchMethodError: org.intellimate.izou.security.replaced.MixerAspect.aspectOf()Lorg/intellimate/izou/security/replaced/MixerAspect;
    at javax.sound.sampled.AudioSystem.getLine(AudioSystem.java:410) ~[?:1.8.0_25]
    at leanderk.izou.playground.ExampleAddOn.prepare(ExampleAddOn.java:41) ~[?:?]
    at org.intellimate.izou.sdk.addon.AddOn.register(AddOn.java:41) ~[?:?]
    at org.intellimate.izou.addon.AddOnManager$$Lambda$19/970865974.run(Unknown Source) ~[?:?]
    at java.util.concurrent.CompletableFuture$AsyncRun.exec(CompletableFuture.java:454) ~[?:1.8.0_25]
    ... 4 more
它似乎没有编织,但为什么呢?我不知道还有什么可以尝试的。我有以下依赖项:

<dependency>
    <groupId>org.aspectj</groupId>
    <artifactId>aspectjweaver</artifactId>
    <version>1.8.5</version>
 </dependency>
 <dependency>
    <groupId>aspectj</groupId>
    <artifactId>aspectjrt</artifactId>
    <version>1.5.4</version>
 </dependency>
为了使事情进一步复杂化,类加载器在另一个项目中,是对该项目的简单maven依赖。 我缺少一些方面的初始化吗?

编辑以澄清答案: 您还必须通过WeavingURLClassloader定义方面,这是我的(示例 - 简化)代码,同样可以应用于您想要混入的每个类。在我的情况下,类已经通过系统类加载器加载,所以我不得不明确地调用define(小心,从不同类加载器加载的相同类是不一样的!)

private Class mixer = null;
......
@Override
public Class<?> loadClass(String className) throws ClassNotFoundException {
   .....
   else if (className.contains("MixerAspect")) {
        InputStream is = this.getResourceAsStream(className.replace('.', '/') + ".class");
        ByteArrayOutputStream buffer = new ByteArrayOutputStream();

        int nRead;
        byte[] data = new byte[16384];

        try {
            while ((nRead = is.read(data, 0, data.length)) != -1) {
                buffer.write(data, 0, nRead);
            }
        } catch (IOException e) {
            throw new ClassNotFoundException("unable to load class", e);
        }

        try {
            buffer.flush();
        } catch (IOException e) {
            throw new ClassNotFoundException("unable to load class", e);
        }
        byte[] array = buffer.toByteArray();
        URL mixerAspect = getResource("org/intellimate/izou/security/replaced/MixerAspect.class");
        try {
            if (mixer == null) {
                mixer = weaver.defineClass(className, array, new CodeSource(mixerAspect, (Certificate[]) null));
            }
            return mixer;
        } catch (IOException e) {
            throw new ClassNotFoundException("unable to define class", e);
        }
    }

2 个答案:

答案 0 :(得分:3)

如果使用注释样式方面并使用javac进行编译,则需要在加载时将方面“完成”并通过weaver本身。如果不这样做,它就无法生成像aspectOf()这样的辅助方法,这些方法将从试图使用方面的其他编织类型中调用。 NoSuchMethodError的{​​{1}}告诉我方面没有被编织。 aspectOf()被调用的事实告诉我其他类型正在成功编织。几个选择:

  • 使用ajc编译你的MixerAspect,这将在编译时添加额外的方法

  • 确保您的编织过程能够编织MixerAspect。确保它加载了其他正在编织的类而不是父加载器?或者让父装载机编织呢?

答案 1 :(得分:1)

是的,我选择了第二个,它在LTW中工作。

<!DOCTYPE aspectj PUBLIC
        "-//AspectJ//DTD//EN" "http://www.eclipse.org/aspectj/dtd/aspectj.dtd">
<aspectj>
    <weaver>
        <!--<weaver options="-verbose -showWeaveInfo -debug">-->
        <include within="com.rabbitmq.client.impl.ChannelN"/>
        <include within="**.MQAspect"/>
    </weaver>
    <aspects>
        <!-- weave in just this aspect -->
        <aspect name="**.MQAspect"/>
    </aspects>
</aspectj>