是否可以使 JSF FacesServlet 与 AspectJ 一起工作?

Is it possible to make JSF FacesServlet work with AspectJ?

我正在尝试编写示例应用程序来展示 JSF 的 FacesServlet 运行 在 tomcat 和 AspectJ 上的集成。我创建了两个项目:

1) JSF 项目:

pom.xml:

<dependencies>
        <!-- JSF 2.0 dependencies -->
    <dependency>
        <groupId>com.pac</groupId>
        <artifactId>aspectj-lib</artifactId>
        <version>1.0-SNAPSHOT</version>
    </dependency>
</dependencies>

<build>
    <finalName>JavaServerFaces</finalName>

    <plugins>
        <plugin>
            <groupId>org.codehaus.mojo</groupId>
            <artifactId>aspectj-maven-plugin</artifactId>
            <version>1.7</version>
            <configuration>
                <aspectLibraries>
                    <aspectLibrary>
                        <groupId>com.pac</groupId>
                        <artifactId>aspectj-lib</artifactId>
                    </aspectLibrary>
                </aspectLibraries>
            </configuration>
            <executions>
                <execution>
                    <goals>
                        <goal>compile</goal>
                    </goals>
                </execution>
            </executions>
        </plugin>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-compiler-plugin</artifactId>
            <version>2.3.1</version>
            <configuration>
                <source>1.7</source>
                <target>1.7</target>
            </configuration>
        </plugin>
    </plugins>
</build>

ManagedBean:

@ManagedBean
@SessionScoped
public class HelloBean implements Serializable {

    private static final long serialVersionUID = 1L;

    private String name;

    public String getName() {
        test();
        return name;
    }

    public void setName(String name) {
        test();
        this.name = name;
    }

    public int test(){
        System.out.println("Test is invoked");
        return 10;
    }

}

2) aspectj-lib 包含所有方面

pom.xml:

<dependencies>
        <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjrt</artifactId>
            <version>1.8.2</version>
        </dependency>
        <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjweaver</artifactId>
            <version>1.8.2</version>
        </dependency>
        <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjtools</artifactId>
            <version>1.8.2</version>
        </dependency>
  </dependencies>

  <build>
        <plugins>
            <plugin>
                <groupId>org.codehaus.mojo</groupId>
                <artifactId>aspectj-maven-plugin</artifactId>
                <version>1.7</version>
                <executions>
                    <execution>
                        <id>compile</id>
                        <goals>
                            <goal>compile</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
        </plugins>
  </build>

TestAspect.aj:

public aspect TestAspect {
    pointcut t(): execution(public !static * *(..));

    int around() : t() {
        System.out.println("Test string");    
        int v = proceed();
        return v * 2;
    }
}

所以,我预计在调用 test() 时应该会出现这个方面。但它没有,我在控制台的输出中看到的是:

Test is invoked
Test is invoked
Test is invoked
Test is invoked

Test string 未打印方面中定义的内容。

如何整合 JSFAspectJ?有文档吗?

也许我应该在 web.xml/faces-config.xml 中添加额外的确认信息或创建另一个配置文件以使其工作?

Documentation reference

答案很简单。我们所要做的就是 编译时编织替换为加载时编织。加载时编织意味着我们将在 JVM 尝试加载它们时编织我们的 类。替换是必要的,因为编译时编织和加载时编织彼此不兼容。所以,假设我们有两个项目:

aspects-lib
    |---pom.xml
    |---src/main/aspect
             |---TestAspect.aj   -- aspect itself


JavaServerFaces
    |---pom.xml
    |---src/main/java
    |          |---TestBean.java    -- The bean which methods we want to intercept
    |---src/main/resources
    |          |---META-INF/aop.xml -- That file configures the load-time weaving
    |---src/main/webapp
               |
        webpages, omited

现在让我们考虑配置。

aop.xml(加载时编织配置):

<aspectj>
  <aspects>
    <aspect name="fully.qualified.ascpect.name"/>
  </aspects>

  <weaver options="-verbose">
    <include within="package.you.want.to.weave.*"/>
  </weaver>
</aspectj>

aspect-lib/pom.xml:

 <dependencies>
        <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjrt</artifactId>
            <version>1.8.2</version>
        </dependency>
        <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjweaver</artifactId>
            <version>1.8.2</version>
        </dependency>
        <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjtools</artifactId>
            <version>1.8.2</version>
        </dependency>
  </dependencies>

  <build>
        <plugins>
            <plugin>
                <groupId>org.codehaus.mojo</groupId>
                <artifactId>aspectj-maven-plugin</artifactId>
                <version>1.7</version>
                <configuration>
                    <!-- IMPORTANT!!!!!! -->
                    <!-- DISABLING COMPILE TIME WEAVING -->
                    <outxml>true</outxml>
               <XterminateAfterCompilation>true</XterminateAfterCompilation>
                    <!-- DISABLING COMPILE TIME WEAVING -->
                </configuration>
                <executions>
                    <execution>
                        <id>compile</id>
                        <goals>
                            <goal>compile</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
        </plugins>
  </build>

JavaServerFaces/pom.xml:

    <dependency>
            <!-- aspect-lib dependency -->
    </dependency>

    <plugin>
         <groupId>org.codehaus.mojo</groupId>
         <artifactId>aspectj-maven-plugin</artifactId>
         <version>1.7</version>
         <configuration>
            <outxml>true</outxml>
            <XterminateAfterCompilation>true</XterminateAfterCompilation>
            <aspectLibraries>
                <aspectLibrary>
                    <!-- your aspect lib -->
                </aspectLibrary>
            </aspectLibraries>
         </configuration>

         <executions>
             <execution>
                 <goals>
                     <goal>compile</goal>
                 </goals>
             </execution>
         </executions>
    </plugin>

还有一件事:您应该将以下选项添加到 JVM 以允许您的 servlet-container/app-server 执行加载时编织:

-javaagent:pathto/aspectjweaver.jar

应将相应的 jar 文件添加到服务器的资源中。