Spring AOP + AspectJ maven 插件 - 内部方法调用不起作用
Posted
技术标签:
【中文标题】Spring AOP + AspectJ maven 插件 - 内部方法调用不起作用【英文标题】:Spring AOP + AspectJ maven plugin - Internal method call doesn't work 【发布时间】:2015-06-06 19:40:42 【问题描述】:Java + Spring + Maven 应用程序。 无法从基于注释的公共方法进行内部调用。
先决条件
-
Java 版本:1.7。
项目:AspectProject > 构建后它将创建 jar 文件。
客户端:AspectClient:具有“AspectProject”的依赖项。
AspectProject
-
pom.xml
<properties>
<java.version>1.7</java.version>
<maven.compiler.source>1.7</maven.compiler.source>
<maven.compiler.target>1.7</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<springframework.version>4.1.2.RELEASE</springframework.version>
<org.aspectj-version>1.7.0</org.aspectj-version>
</properties>
<dependencies>
<!-- Spring -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>$springframework.version</version>
</dependency>
<!-- AspectJ dependencies -->
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjrt</artifactId>
<version>$org.aspectj-version</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjtools</artifactId>
<version>$org.aspectj-version</version>
</dependency>
</dependencies>
<build>
<sourceDirectory>src/main/java</sourceDirectory>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.1</version>
<!-- compile for Java 1.7 -->
<configuration>
<source>$maven.compiler.source</source>
<target>$maven.compiler.target</target>
<encoding>$project.build.sourceEncoding</encoding>
</configuration>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>aspectj-maven-plugin</artifactId>
<version>1.4</version>
<dependencies>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjrt</artifactId>
<version>$org.aspectj-version</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjtools</artifactId>
<version>$org.aspectj-version</version>
</dependency>
</dependencies>
<executions>
<execution>
<phase>process-sources</phase>
<goals>
<goal>compile</goal>
<goal>test-compile</goal>
</goals>
<configuration>
<complianceLevel>$maven.compiler.source</complianceLevel>
<source>$maven.compiler.source</source>
<target>$maven.compiler.target</target>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
-
AspectProvider
@Aspect
public class AspectProvider
/**
* This is the point cut for all get Method with @TestAnnotation annotation
*/
@Pointcut("execution(* get*()) && @annotation(aTestAnnotation)")
public void getMethodPointcut(TestAnnotation aTestAnnotation)
@Around("getMethodPointcut(aTestAnnotation)")
public Object getConfiguration(ProceedingJoinPoint iJoinPoint, TestAnnotation aTestAnnotation) throws Throwable
return getValueFromISTCompositeConfiguration(iJoinPoint, aTestAnnotation);
private Object getValueFromISTCompositeConfiguration(final ProceedingJoinPoint iProceedingJoinPoint, TestAnnotation aTestAnnotation) throws Throwable
Object aReturnValue = null;
if (aTestAnnotation.value() != null)
System.out.println("ASPECT: Returning annotation value.");
aReturnValue = aTestAnnotation.value();
else
System.out.println("MISSING_GETTER_PROPERTY");
if(aReturnValue == null)
aReturnValue = iProceedingJoinPoint.proceed();
return aReturnValue;
-
注释“TestAnnotation”
@Component
@Target(ElementType.METHOD, ElementType.PARAMETER, ElementType.ANNOTATION_TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface TestAnnotation
String value();
AspectClient
-
pom.xml
<properties>
<java.version>1.7</java.version>
<maven.compiler.source>1.7</maven.compiler.source>
<maven.compiler.target>1.7</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<aspectProject.version>0.0.1-SNAPSHOT</aspectProject.version>
<spring-framework.version>4.1.2.RELEASE</spring-framework.version>
<org.aspectj-version>1.7.0</org.aspectj-version>
</properties>
<dependencies>
<!-- Spring -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>$spring-framework.version</version>
</dependency>
<!-- AspectProject dependencies -->
<dependency>
<groupId>com.example.aop</groupId>
<artifactId>AspectProject</artifactId>
<version>$aspectProject.version</version>
</dependency>
</dependencies>
<build>
<sourceDirectory>src/main/java/</sourceDirectory>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.1</version>
<!-- compile for Java 1.7 -->
<configuration>
<source>$maven.compiler.source</source>
<target>$maven.compiler.target</target>
<encoding>$project.build.sourceEncoding</encoding>
</configuration>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>aspectj-maven-plugin</artifactId>
<version>1.4</version>
<configuration>
<showWeaveInfo>true</showWeaveInfo>
<aspectLibraries>
<aspectLibrary>
<groupId>com.example.aop</groupId>
<artifactId>AspectProject</artifactId>
</aspectLibrary>
</aspectLibraries>
<complianceLevel>$maven.compiler.source</complianceLevel>
<source>$maven.compiler.source</source>
<target>$maven.compiler.target</target>
</configuration>
<executions>
<execution>
<phase>process-sources</phase>
<goals>
<goal>compile</goal>
<goal>test-compile</goal>
</goals>
</execution>
</executions>
<dependencies>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjrt</artifactId>
<version>$org.aspectj-version</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjtools</artifactId>
<version>$org.aspectj-version</version>
</dependency>
</dependencies>
</plugin>
</plugins>
</build>
-
服务类
@Component
public class TestService
private String value;
public void internalCall()
System.out.println("INTERNAL_CALL :"+ getValue());
@TestAnnotation("RETURNED_FROM_ASPECT_CALL")
public String getValue()
return value;
public void setValue(String iValue)
this.value = iValue;
-
Spring context.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.0.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd">
<!-- Enable AspectJ style of Spring AOP -->
<context:component-scan base-package="com.example.aop.client" />
<aop:aspectj-autoproxy />
<bean name="TestService" class="com.example.aop.client.service.TestService" />
<!-- Configure Aspect Beans, without this Aspects advice wont execute -->
<bean name="aspectProvider" class="com.example.aop.aspect.AspectProvider"/>
</beans>
-
主类
public class SpringMain
public static void main(String[] args)
ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext("spring.xml");
TestService aTestService = ctx.getBean("TestService", TestService.class);
System.out.println("EXTERNAL_CALL: "+aTestService.getValue());
aTestService.internalCall();
ctx.close();
输出:
ASPECT: Returning annotation value.
EXTERNAL_CALL:RETURNED_FROM_ASPECT_CALL
INTERNAL_CALL: **null**
预期:
ASPECT: Returning annotation value.
EXTERNAL_CALL: RETURNED_FROM_ASPECT_CALL
INTERNAL_CALL: **RETURNED_FROM_ASPECT_CALL**
如果我遗漏任何条目或需要更改配置,请告知。提前感谢您的宝贵时间。
【问题讨论】:
【参考方案1】:您所做的有点奇怪,因为一方面您将 Spring 配置为使用(自动)基于代理的 Spring AOP,另一方面您使用 AspectJ Maven 插件来使用本机 AspectJ 并进行编译时编织。请决定你想走哪条路:
对于 Spring AOP,您不需要 AspectJ 编译器,但随后您会坚持使用基于代理的“AOP lite”方法,其代价是内部调用不会被切面拦截,因为它们不通过代理,而是通过this
(原始对象)。
对于成熟的 AspectJ,您可以配置 Spring 以使用 LTW(加载时编织),如手册章节 Using AspectJ with Spring applications 中所述。或者,您也可以使用编译时编织,但这不是必需的,除非您在应用程序启动期间遇到性能问题。
【讨论】:
感谢 Kriegaex。我是 aop 概念的新手。你是对的,我错误地弄乱了 Spring-aop 和 AspectJ 编译器。我想要 AspectJ 功能,以便内部调用被切面拦截。以上是关于Spring AOP + AspectJ maven 插件 - 内部方法调用不起作用的主要内容,如果未能解决你的问题,请参考以下文章