Java 为什么我的方面是在其原始设置中执行的,而不是在打包为单独的jar并从其他地方调用时执行的?
我是aspectj的新手 我编写了以下方面,旨在向类型为Java 为什么我的方面是在其原始设置中执行的,而不是在打包为单独的jar并从其他地方调用时执行的?,java,eclipse,jar,aspectj,Java,Eclipse,Jar,Aspectj,我是aspectj的新手 我编写了以下方面,旨在向类型为public*doSomething*(..)的函数调用添加日志记录。如果我的主类是同一个项目的一部分,则方面的编织将在没有故障的情况下执行,代码将执行。如果我将编织好的代码打包到一个jar中,并从另一个eclipse项目调用它,则不会执行建议。另一个场景是将方面(.aj)打包到一个单独的jar中,并将该jar添加到eclipse中的“方面路径”,这使eclipse能够正确地编织方面。问题是我需要将其包装到一个jar中,并从其他地方调用代码
public*doSomething*(..)
的函数调用添加日志记录。如果我的主类是同一个项目的一部分,则方面的编织将在没有故障的情况下执行,代码将执行。如果我将编织好的代码打包到一个jar中,并从另一个eclipse项目调用它,则不会执行建议。另一个场景是将方面(.aj)打包到一个单独的jar中,并将该jar添加到eclipse中的“方面路径”,这使eclipse能够正确地编织方面。问题是我需要将其包装到一个jar中,并从其他地方调用代码。这也不起作用(我想这并不奇怪……)为什么
import org.aspectj.lang.JoinPoint;
导入org.aspectj.lang.reflect.CodeSignature;
导入org.apache.log4j.Logger;
公共方面日志记录{
切入点allPublic():!cflow(调用(public void main(..)&&(调用(public*doSomething*(..));
私有静态最终记录器log=Logger.getLogger(“Logging.aspect”);
@SuppressWarnings({“未选中”、“未使用”})
私有void打印参数(JoinPoint jp){
CodeSignature methodSignature=(CodeSignature)jp.getSignature();
字符串methodName=methodSignature.getName();
对象[]ParamName=methodSignature.getParameterNames();
类[]paramTypes=(类[])methodSignature.getParameterTypes();
Object[]paramObjects=jp.getArgs();
StringBuffer infoMsg=新的StringBuffer();
append(“输入函数:”+methodName);
if(paramNames!=null&¶mNames.length>0){
如果(paramNames.length==1){
infoMsg.append(“带输入参数:[“+paramNames[1]+”]=[“+paramObjects[1]+”]);
}
否则{
append(“带有输入参数:”);
}
for(int i=1;i
应该建议的班级:
public class Main {
private static final Logger log = Logger.getLogger("A.class");
public static void doSomethingAa(int number, String message, Map<String, String> map){
log.debug("A");
}
public static void doSomethingB(int id, String name){
log.debug("B");
}
public static void main(String[] args){
Map<String, String> map1 = new TreeMap<String, String>();
Map<String, String> map2 = new TreeMap<String, String>();
map1.put("FirstKey", "FirstValue");
map1.put("SecondKey", "SecondValue");
map2.put("Tal", "Guy");
map2.put("Happy", "Birthday");
A.doSomethingAa(17, "Tal", map1);
A.doSomethingAa(35, "Guy", map2);
A.doSomethingB(12, "TalG");
A.doSomethingB(40, "GuyG");
System.out.println("Finished running main");
}
}
公共类主{
私有静态最终记录器log=Logger.getLogger(“A.class”);
公共静态void doSomethingAa(整数、字符串消息、地图){
log.debug(“A”);
}
公共静态void doSomethingB(int-id,字符串名){
log.debug(“B”);
}
公共静态void main(字符串[]args){
Map map1=新树映射();
Map map2=新树映射();
map1.put(“第一键”、“第一值”);
map1.put(“第二个键”、“第二个值”);
地图2.放置(“Tal”、“Guy”);
map2.put(“快乐”、“生日”);
A.doSomethingAa(17,“Tal”,map1);
A.doSomethingAa(35,“Guy”,map2);
A.doSomethingB(12,“TalG”);
A.doSomethingB(40,“GuyG”);
System.out.println(“完成运行的主管道”);
}
}
谢谢大家 我还没有尝试在插件开发中使用aspectj,所以可能还有一些额外的东西。但是,为了确保目标在编译时正确编织并可以运行,您需要做一些事情
- 正在编织的插件需要依赖于包含方面的插件
- 方面需要位于类路径上的导出包中
- 目标插件需要在类路径上有aspectjrt,这样它才能处理方面
- 编译目标时,需要使用aspectj编译器来编织目标
更新,我无法重现您的问题(即,它在我的盒子上工作正常)。为了复制这种情况,我在源目录中创建了一个带有单个Logging.aj文件的AspectJ项目。我将其作为jar文件(称为logging.jar)导出到另一个项目的根目录(另一个项目也设置为包含“Main”类的AspectJ项目)。然后,我修改了“main”项目的方面路径,以包括logging.jar和方面,并将建议编织到每个doSomethingAa()和doSomethingB()方法调用中 我在代码中发现的唯一问题是,静态方法调用是针对“A”而不是“Main” 以下是主项目的.classpath文件中的条目:
<classpathentry kind="lib" path="logging.jar">
<attributes>
<attribute name="org.eclipse.ajdt.aspectpath"
value="org.eclipse.ajdt.aspectpath"/>
</attributes>
</classpathentry>
运行时,此操作失败,并出现NoClassDefFoundError:
Exception in thread "main" java.lang.NoClassDefFoundError: org/aspectj/lang/Signature
at Client.main(Client.java:6)
Caused by: java.lang.ClassNotFoundException: org.aspectj.lang.Signature
为了解决这个问题,我修改了aj_客户端的.classpath,使其上有aspectjrt(通过手动将AspectJ运行时库类路径容器添加到.classpath),然后重新运行,程序执行并输出日志语句:
Entering function: doSomethingAa with input parameters: [java.lang.String message] = [Tal] [java.util.Map map] = [{FirstKey=FirstValue, SecondKey=SecondValue}]
log4j:WARN No appenders could be found for logger (A.class).
log4j:WARN Please initialize the log4j system properly.
Exit function: void target.Main.doSomethingAa(int, String, Map)
Entering function: doSomethingAa with input parameters: [java.lang.String message] = [Guy] [java.util.Map map] = [{Happy=Birthday, Tal=Guy}]
Exit function: void target.Main.doSomethingAa(int, String, Map)
Entering function: doSomethingB with input parameters: [java.lang.String name] = [TalG]
Exit function: void target.Main.doSomethingB(int, String)
Entering function: doSomethingB with input parameters: [java.lang.String name] = [GuyG]
Exit function: void target.Main.doSomethingB(int, String)
Finished running main
aj_客户端的.classpath文件如下所示:
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry kind="src" path="src/main/java"/>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
<classpathentry kind="con" path="org.eclipse.ajdt.core.ASPECTJRT_CONTAINER"/>
<!-- the other jars for the logging and target projects -->
<classpathentry kind="lib" path="/aj_target/target.jar"/>
<classpathentry kind="lib" path="/aj_target/log4j-1.2.14.jar"/>
<classpathentry kind="lib" path="/aj_target/logging.jar"/>
<classpathentry kind="output" path="target/classes"/>
</classpath>
注意:在清理、构建和导出target.jar之前,您需要小心确保已经清理、构建和导出了logging.jar,然后才清理客户机项目。如果你把订单搞砸了,你会得到不匹配的内容
摘要 因此,只要您的客户机项目引用了使用AspectJ构建的“target.jar”(因此Logging.aj是编织的),和您的类路径上有一个aspectjrt.jar,并且您已经正确配置了log4j,日志记录就会被输出
您可以通过添加类路径容器或指定兼容aspectjrt.jar的路径来指定aspectjrt依赖关系这是一个有趣的问题,如果没有其他人可以回答,我会在有机会的时候看一看。所有的研究都是+1。这将使赏金
Entering function: doSomethingAa with input parameters: [java.lang.String message] = [Tal] [java.util.Map map] = [{FirstKey=FirstValue, SecondKey=SecondValue}]
log4j:WARN No appenders could be found for logger (A.class).
log4j:WARN Please initialize the log4j system properly.
Exit function: void target.Main.doSomethingAa(int, String, Map)
Entering function: doSomethingAa with input parameters: [java.lang.String message] = [Guy] [java.util.Map map] = [{Happy=Birthday, Tal=Guy}]
Exit function: void target.Main.doSomethingAa(int, String, Map)
Entering function: doSomethingB with input parameters: [java.lang.String name] = [TalG]
Exit function: void target.Main.doSomethingB(int, String)
Entering function: doSomethingB with input parameters: [java.lang.String name] = [GuyG]
Exit function: void target.Main.doSomethingB(int, String)
Finished running main
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry kind="src" path="src/main/java"/>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
<classpathentry kind="con" path="org.eclipse.ajdt.core.ASPECTJRT_CONTAINER"/>
<!-- the other jars for the logging and target projects -->
<classpathentry kind="lib" path="/aj_target/target.jar"/>
<classpathentry kind="lib" path="/aj_target/log4j-1.2.14.jar"/>
<classpathentry kind="lib" path="/aj_target/logging.jar"/>
<classpathentry kind="output" path="target/classes"/>
</classpath>
<classpathentry kind="con" path="org.eclipse.ajdt.core.ASPECTJRT_CONTAINER"/>
<!--aspectjrt from Maven repository-->
<classpathentry kind="lib" path="C:/maven-2.2.0/repo/aspectj/aspectjrt/1.5.3/aspectjrt-1.5.3.jar"/>
<!--aspectjrt from Eclipse plugin -->
<classpathentry kind="lib" path="C:/eclipse-3.5/eclipse/plugins/org.aspectj.runtime_1.6.5.20090618034232/aspectjrt.jar"/>
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/">
<appender name="console" class="org.apache.log4j.ConsoleAppender">
<param name="Target" value="System.out"/>
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern" value="%-5p %c{1} - %m%n"/>
</layout>
</appender>
<root>
<priority value ="debug" />
<appender-ref ref="console" />
</root>
</log4j:configuration>
DEBUG class - A
INFO Logging - Exit function: void target.Main.doSomethingAa(int, String, Map)
INFO Logging - Entering function: doSomethingB with input parameters: [java.lang.String name] = [TalG]
DEBUG class - B
INFO Logging - Exit function: void target.Main.doSomethingB(int, String)
INFO Logging - Entering function: doSomethingB with input parameters: [java.lang.String name] = [GuyG]
DEBUG class - B
INFO Logging - Exit function: void target.Main.doSomethingB(int, String)
Finished running main