关于编织成JAR文件的文档很多,例如AspectJ in Action: Second Edition书中描述的示例。
但是,我几乎看不到有关编织到WAR文件中的任何问题。由于WAR文件和AspectJ库的流行,我很难相信它不受支持,因此我希望能找到一些答案。
假设您有一个“旧版” Java项目,该项目正在使用maven-war-plugin插件打包为WAR文件。请记住,由于涉及风险,几乎不可能将其从WAR更改为JAR包装。
现在,假设我想为一些跨领域功能引入AOP。由于我们应用程序的性质,我最好的选择是创建一个单独的项目。因此,基本上,方面类将与旧项目不在同一项目中。它将是分开的。
在这部分之后,我被卡住了。通过在线阅读本书和其他文档,似乎可以采用两种方法进行编译时编织:
<build>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>aspectj-maven-plugin</artifactId>
<executions>
<execution>
<goals>
<goal>compile</goal>
</goals>
</execution>
</executions>
<configuration>
<weaveDependencies>
<weaveDependency>
<groupId>ajia.helloworld</groupId>
<artifactId>application-unwoven</artifactId>
</weaveDependency>
</weaveDependencies>
<aspectLibraries>
<aspectLibrary>
<groupId>ajia.helloworld</groupId>
<artifactId>profiling-aspect-library</artifactId>
</aspectLibrary>
</aspectLibraries>
</configuration>
</plugin>
</plugins>
</build>
第二个选项的问题是<weaveDependency>
要求应用程序为JAR文件。据我所知,Atleast。
我确实在AspectJ邮件列表中遇到了类似的问题:http://aspectj.2085585.n4.nabble.com/Weaving-into-a-war-file-td2082924.html。 万一链接过期,问题的答案是:
您需要将其拆开,编织.jar并将其放回原处。 您不能直接在战争中编织广口瓶
但这有可能吗?我也没有任何文档。
SO上存在类似的问题,这些问题根本没有任何答复,或者是错误/过时的。
由于我不知道下一步该怎么做,因此我将不胜感激。
答案 0 :(得分:1)
我将尝试提出两种不同的解决方案,然后您可以选择/选择或混合/匹配实施解决方案的方式。
示例1 :已要求您将一些文本转储到pg_dump
中的org.apache.log4j.Logger.info(Object o)
方法的执行前和执行后。
(这是一个非常的示例,但我使用它是因为过去我被要求做一些不完全不同的事情!)
我假设您使用的是Multi-Module Maven Project。
要实现此目的,我们可以使用log4j
jar(已编译类),对其应用Aspect,然后吐出一组新的加载时编织的已编译类。我们通过利用您已经在其自身模块中调用的weaveDependency功能来实现此目的。因此,如下所述,您将不再依赖log4j
,而将依赖log4j
。
请牢记这一点,从而创建您的项目层次结构:
ltwjar-enhanced-log4j
将您的父pom.xml设置为如下所示(为了方便/一致起见,我们在此处设置了几个属性-还有其他控制版本控制的方法,例如dependencyManagement和imported depdendencies,但是那是一个不同的问题!):
ltwjar
/ltwjar-ltwjar-enhanced-log4j
/ltwjar-runtime
像这样设置<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.example</groupId>
<artifactId>ltwjar</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>pom</packaging>
<properties>
<aspectj.version>1.8.13</aspectj.version>
<log4j.version>1.2.17</log4j.version>
</properties>
<modules>
<module>ltwjar-enhanced-log4j</module>
<module>ltwjar-runtime</module>
</modules>
</project>
pom.xml:
ltwjar-enhanced-log4j
现在,让我们设置存根“运行时”模块,以便在日志记录时通过配置pom.xml来利用其加载时日志log4j <project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.example</groupId>
<artifactId>ltwjar</artifactId>
<version>0.0.1-SNAPSHOT</version>
</parent>
<artifactId>ltwjar-enhanced-log4j</artifactId>
<dependencies>
<!-- we need this because the post-weave classes may (will) depend on aspectj types -->
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjrt</artifactId>
<version>${aspectj.version}</version>
</dependency>
<!-- ATTENTION! Scope this to provided otherwise it won't work - because of transitive dependencies,
anything that depends on this module will end up getting the _actual_ log4j classes versus the ones we are enriching! -->
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>${log4j.version}</version>
<scope>provided</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>aspectj-maven-plugin</artifactId>
<version>1.11</version>
<configuration>
<!-- instruct aspectj to weave the classes in the jar! -->
<weaveDependencies>
<weaveDependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
</weaveDependency>
</weaveDependencies>
<Xlint>warning</Xlint>
</configuration>
<executions>
<execution>
<goals>
<goal>compile</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
:
ltw-enhanced-log4j
好的,这就是我们的框架设置。现在,让我们创建一个无意义的方面来说明这一点!
在<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.example</groupId>
<artifactId>ltwjar</artifactId>
<version>0.0.1-SNAPSHOT</version>
</parent>
<artifactId>ltwjar-runtime</artifactId>
<dependencies>
<!-- Note that this module doesn't care (itself) about aspectj.
It _does_ care that it depends on the ltwjar-enhanced-log4j module
and not log4j, however. So let's depend on that! -->
<dependency>
<groupId>com.example</groupId>
<artifactId>ltwjar-enhanced-log4j</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
</dependencies>
</project>
中创建类型ltwjar-enhanced-log4j
,如下所示:
com.example.aspect.LoggingAspect
最后在package com.example.aspect;
import org.apache.log4j.Logger;
public aspect LoggingAspect {
// this pointcut will match "info(Object o)" method executions where the
// target is an instanceof Logger
pointcut logInfoWithObject(Object obj, Logger logger) :
execution(void info(Object)) && args(obj) && target(logger);
// here is our advice - simply sysout something before the execution
// proceeds and after it has finished - regardless of outcome (exception
// or not).
void around(Object obj, Logger logger) : logInfoWithObject(obj, logger) {
System.out.println("Before Logger.info(Object o)");
try {
proceed(obj, logger);
} finally {
System.out.println("After Logger.info(Object o)");
}
}
}
中,创建一个驱动程序/线束,以显示所有工作情况。输入ltwjar-runtime
:
com.example.Driver
现在从您的父项目中运行package com.example;
import org.apache.log4j.Logger;
public class Driver {
private static final Logger LOG = Logger.getLogger(Driver.class);
public static void main(String[] args) {
LOG.info("In main");
}
}
,然后运行mvn clean install
。
输出应该是这样的(因为您的类路径中没有log4j.xml):
mvn -pl ltwjar-runtime exec:java -Dexec.mainClass="com.example.Driver"
注意第一行和最后一行。
这是怎么回事:
Before Logger.info(Object o)
log4j:WARN No appenders could be found for logger (com.example.Driver).
log4j:WARN Please initialize the log4j system properly.
log4j:WARN See http://logging.apache.org/log4j/1.2/faq.html#noconfig for more info.
After Logger.info(Object o)
中,我们通过在ltwjar-enhanced-log4j
周围包装建议来“增强” log4j Logger.info(Object o)
重新包装到一个包含机织类型的新罐log4j.jar
中ltwjar-enhanced-log4j.jar
而不是 ltwjar-enhanced-log4j.jar
... 好吧,这如何适合最初询问的warfile?
简单-不要在warfile模块中放置任何代码。如果必须在其中放置一些东西,请对其进行配置。而是将所有代码移至log4j
或yourproject-domain
或...(在此处插入模块名称),并使warfile依赖于 that 模块。这是一个好习惯,因为它启用了Separation of Concerns:您的应用程序不应该知道它在warfile伞下运行;它可以像Spring Boot tomcat uberwar等一样轻松地运行。包装方面的关注点(war)与业务方面的关注点(domain)不同。
今天晚上我将更新另一个共享方面库的示例,除非有人殴打我。另外,如果其中一些没有意义,请大声疾呼!