gpt4 book ai didi

java - AspectJ:尝试使用外部 aop.xml 文件时出现类加载问题

转载 作者:塔克拉玛干 更新时间:2023-11-01 22:11:44 25 4
gpt4 key购买 nike

我试图将 aop.xml 的配置外部化,所以我从 META-INF 中删除了 aop.xml 并使其在服务器中可用以通过以下方式进行手动配置系统管理员。

当我尝试使用外部 aop.xml 时

-Dorg.aspectj.weaver.loadtime.configuration="file:D:\Workspace\tomcat7\shared\lib\aop.xml"

我得到 java.lang.RuntimeException: Cannot register non aspect: aspectclass.... 主要是因为 aj casses 还没有被 AppClassLoader 加载。下次它尝试从 WebAppClassLoader 注册方面(在加载所有类之后),它工作正常,但我仍然从第一次尝试注册它时记录异常。

ClassLoaderWeavingAdaptor.java 第 307 行捕获并记录异常。

当以下行被调用时: success = registerAspects(weaver, loader, definitions);

异常被捕获并记录。

    try {
registerOptions(weaver, loader, definitions);
registerAspectExclude(weaver, loader, definitions);
registerAspectInclude(weaver, loader, definitions);
success = registerAspects(weaver, loader, definitions);
registerIncludeExclude(weaver, loader, definitions);
registerDump(weaver, loader, definitions);
} catch (Exception ex) {
trace.error("register definition failed", ex);
success = false;
warn("register definition failed", (ex instanceof AbortException) ? null : ex);
}

BcelWeaver.java 中的以下行恰好抛出异常

if (type.isAspect()) {
......
} else {
// FIXME AV - better warning upon no such aspect from aop.xml
RuntimeException ex = new RuntimeException("Cannot register non aspect: " + type.getName() + " , " + aspectName);
if (trace.isTraceEnabled()) {
trace.exit("addLibraryAspect", ex);
}
throw ex;
}

当方面尚未加载时,如何防止类加载器将错误记录到控制台。我正在考虑从源文件中注释记录异常的行并重建 aspectjweaver jar 文件,但正在寻找一个更好的解决方案而不修改 aspectj 源。

最佳答案

我不确定是否有简单的方法可以解决您的问题。正如我所说,我以前没有使用过 AspectJ,但我相信这是编织者的错误行为。

问题描述:在引导过程中,代理尝试不仅将编织应用到 WebAppClassLoader,而且将其应用到整个类加载器链(每个类加载器一次),即:sun.misc.Launcher$AppClassLoader, sun.misc.Launcher$ExtClassLoader, org.apache.catalina.loader.StandardClassLoader(tomcat 的类加载器)。当您使用 META-INF/aop.xml 方法时,它会禁用上述类加载器的编织,因为“配置文件不可用”(如果启用 verbose 模式,您可以在控制台中查看这些消息)。当您使用文件配置方法时,配置可用于链中的所有类加载器。因为它确实找到了一个配置文件,代理解析了定义,它没有找到方面的类并显示错误。

奇怪的是,正如configuration documentation中所描述的那样如果您使用 WeavingURLClassLoader 方法进行加载时编织,“...它还允许用户通过类加载器明确限制可以编织哪些类”。所以这实际上是类加载器方法可以具有但代理方法没有的特性(!)。 (不幸的是我无法使用这种方法)

好(和坏)消息:好消息是您可以轻松创建自己的代理,该代理将忽略上述类加载器的编织。坏消息是限制每个类加载器的编织是不够的,因为如果您在同一台服务器上有其他应用程序,Tomcat 仍会使用 WebAppClassLoader 来加载它们,因此您仍然会收到这些应用程序的错误消息。 (在这种情况下,也许您也可以扩展下面的类来过滤包/类)。

您可以在下面找到修改后的代理的两个类。要使用它们,您需要执行以下操作:

  • aspectjweaver.jar 解压到一个文件夹
  • org/aspectj/weaver/loadtime 下创建一个新文件夹 filter 以匹配包名称,并将编译后的两个新类放在那里。
  • 编辑 META-INF/MANIFEST.MF 文件并更改行

    Premain-Class: org.aspectj.weaver.loadtime.Agent
    预维护类:org.aspectj.weaver.loadtime.filter.FilterAgent

  • 重新打包,新代理准备就绪。

  • 启动 JVM 时,您现在可以传递一个新的系统属性,其中包含您想要忽略的类加载器的逗号分隔列表,即 -Dorg.aspectj.weaver.loadtime.filter=sun.misc.Launcher$AppClassLoader ,sun.misc.Launcher$ExtClassLoader,org.apache.catalina.loader.StandardClassLoader(我设置了CATALINA_OPTS)。

这些类是原始代理类 AgentClassPreProcessorAgentAdapter 的修改副本。我添加的唯一代码是解析上述系统属性(如果存在)并忽略对我们不感兴趣的类加载器的调用的部分。

使用风险自负:)希望对您有所帮助

package org.aspectj.weaver.loadtime.filter;

import java.lang.instrument.ClassFileTransformer;
import java.lang.instrument.Instrumentation;

public class FilterAgent {

private static Instrumentation s_instrumentation;

// Use our own version of ClassFileTransformer that would filter out selected classloaders
private static ClassFileTransformer s_transformer = new ClassPreprocessorFilteredAdapter();

/**
* JSR-163 preMain Agent entry method
*
* @param options
* @param instrumentation
*/
public static void premain(String options, Instrumentation instrumentation) {
/* Handle duplicate agents */
if (s_instrumentation != null) {
return;
}
s_instrumentation = instrumentation;
s_instrumentation.addTransformer(s_transformer);
}

public static Instrumentation getInstrumentation() {
if (s_instrumentation == null) {
throw new UnsupportedOperationException("Java 5 was not started with preMain -javaagent for AspectJ");
}
return s_instrumentation;
}
}
//-----------------------------------------------------------------------------------
package org.aspectj.weaver.loadtime.filter;

import java.lang.instrument.ClassFileTransformer;
import java.lang.instrument.IllegalClassFormatException;
import java.security.ProtectionDomain;
import java.util.HashMap;
import java.util.Map;

import org.aspectj.weaver.loadtime.Aj;
import org.aspectj.weaver.loadtime.ClassPreProcessor;


public class ClassPreprocessorFilteredAdapter implements ClassFileTransformer {

/**
* Concrete preprocessor.
*/
private static ClassPreProcessor s_preProcessor;

private static Map<String, String> ignoredClassloaderNames = new HashMap<String, String>();

static {
try {
s_preProcessor = new Aj();
s_preProcessor.initialize();


String ignoredLoaders = System.getProperty("org.aspectj.weaver.loadtime.filter", "");
if (ignoredLoaders.length() > 0) {
String[] loaders = ignoredLoaders.split(",");

for (String s : loaders) {
s = s.trim();
ignoredClassloaderNames.put(s, s);
System.out.println("---> Will filtered out classloader: " + s);
}
}

} catch (Exception e) {
throw new ExceptionInInitializerError("could not initialize JSR163 preprocessor due to: " + e.toString());
}
}

/**
* Invokes the weaver to modify some set of input bytes.
*
* @param loader the defining class loader
* @param className the name of class being loaded
* @param classBeingRedefined is set when hotswap is being attempted
* @param protectionDomain the protection domain for the class being loaded
* @param bytes the incoming bytes (before weaving)
* @return the woven bytes
*/
@Override
public byte[] transform(ClassLoader loader, String className, Class<?> classBeingRedefined, ProtectionDomain protectionDomain, byte[] bytes) throws IllegalClassFormatException {
if (classBeingRedefined != null) {
System.err.println("INFO: (Enh120375): AspectJ attempting reweave of '" + className + "'");
}

String loaderName = loader.getClass().getName();
if (shouldIgnoreClassLoader(loaderName)) {
return bytes;
}
return s_preProcessor.preProcess(className, bytes, loader, protectionDomain);
}

private boolean shouldIgnoreClassLoader(String loaderName) {
boolean result = false;
String ignoredLoader = ignoredClassloaderNames.get(loaderName);
if (ignoredLoader != null) {
result = true; // if the loader name exists in the map we will ignore weaving
}
return result;
}
}

关于java - AspectJ:尝试使用外部 aop.xml 文件时出现类加载问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18194719/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com