我试图为在子类中实现的抽象方法创建切入点,但是AOP从未被调用。
这是我的最小Java代码:
package com.example;
public class Service {
private ParentAbstractClass clazz;
public Service(ParentAbstractClass clazz) {
this.clazz = clazz;
}
public void process() {
clazz.method();
}
}
这是服务类,它具有要注入的类的抽象,并调用方法。
我的抽象类具有一些通用的逻辑,而实现特定的代码则是一种抽象方法。
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
中,我所做的事情本质上是事务性的,并且我需要手动控制事务,但是我的方面类从未被调用。有人可以帮我找出我犯了什么错误。
谢谢。
答案 0 :(得分:1)
该问题是由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>