我正在尝试为子类中实现的抽象方法创建切入点,但AOP永远不会被调用。
这是我的最小Java代码:
package com.example;
public class Service {
private ParentAbstractClass clazz;
public Service(ParentAbstractClass clazz) {
this.clazz = clazz;
}
public void process() {
clazz.method();
}
}
这是一个服务类,它具有要注入的Class的抽象,并且它调用一个方法。
我的抽象类有一些共同的逻辑和一个实现特定的代码,它是一个抽象的方法。
package com.example;
import java.util.List;
public abstract class ParentAbstractClass {
public void method() {
abstractMethod(List.of("test"));
}
public abstract void abstractMethod(List<String> names);
}
这是为抽象方法提供实现的类。
package com.example;
import java.util.List;
public class ConcreteClass extends ParentAbstractClass {
@Override
public void abstractMethod(List<String> names) {
System.out.println("Look up! AOP should have executed");
}
}
通过这个设置,我使用spring XML来配置我的bean。
<bean id = "clazz" class="com.example.ConcreteClass"/>
<bean id="myservice" class="com.example.Service">
<constructor-arg ref="clazz"/>
</bean>
<bean id = "aspect" class="com.exmple.TxAspect"/>
<aop:config>
<aop:aspect id="mergeEnableAspect" ref="aspect">
<aop:pointcut id="mergeServicePointCut"
expression="execution(* com.example.ConcreteClass.abstractMethod(..))"/>
<aop:around pointcut-ref="mergeServicePointCut" method="test" arg-names="pjp"/>
</aop:aspect>
</aop:config>
最后是AOP课程:
import org.aspectj.lang.ProceedingJoinPoint;
public class TxAspect {
public void test(ProceedingJoinPoint pjp) {
System.out.println("I am not going to do anything");
}
}
在我的abstractMethod
中,我正在做一些事务性的事情,我有业务需要手动控制事务但是,我的方面类永远不会被调用。有人可以帮我解决我做错了什么。
谢谢。
问题是由Spring AOP实现的约束引起的。以下是Spring documentation的引用:
由于Spring的AOP框架基于代理的特性,根据定义,目标对象内的调用不会被截获。对于JDK代理,只能拦截代理上的公共接口方法调用。使用CGLIB,代理上的公共和受保护方法调用被截获(如果需要,甚至是包可见的方法)。但是,通过代理进行的常见交互应始终通过公共签名进行设计。
请注意,切入点定义通常与任何截获的方法匹配。如果切入点严格意义上是公开的,即使在通过代理进行潜在非公共交互的CGLIB代理方案中,也需要相应地定义切入点。
如果您的拦截需要包括目标类中的方法调用甚至构造函数,请考虑使用Spring驱动的本机AspectJ编织而不是Spring的基于代理的AOP框架。这构成了具有不同特征的不同AOP使用模式,因此在做出决定之前一定要熟悉编织。
因此,您有两种可能的方法来解决问题:
AspectJ方法简而言之:
修改事务方面如下:
package com.example;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
@Aspect
public class TxAspect {
@Around("methodsToBeProfiled()")
public void test(ProceedingJoinPoint pjp) throws Throwable {
System.out.println("I am not going to do anything");
pjp.proceed();
}
@Pointcut("execution(* com.example.ConcreteClass.abstractMethod(..))")
public void methodsToBeProfiled(){}
}
减少XML配置如下:
<bean id="clazz" class="com.example.ConcreteClass"/>
<bean id="myservice" class="com.example.Service">
<constructor-arg ref="clazz"/>
</bean>
使用以下maven插件编译应用程序:
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>aspectj-maven-plugin</artifactId>
<version>1.11</version>
<dependencies>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjtools</artifactId>
<version>${ascpectj.version}</version>
</dependency>
</dependencies>
<configuration>
<source>1.8</source>
<target>1.8</target>
<complianceLevel>1.8</complianceLevel>
</configuration>
<executions>
<execution>
<goals>
<goal>compile</goal>
<goal>test-compile</goal>
</goals>
</execution>
</executions>
</plugin>