gpt4 book ai didi

java - 如何为抽象方法创建切入点

转载 作者:行者123 更新时间:2023-11-30 05:47:52 25 4
gpt4 key购买 nike

我试图为子类中实现的抽象方法创建切入点,但 AOP 永远不会被调用。

这是我的最小 Java 代码:

package com.example;

public class Service {
private ParentAbstractClass clazz;

public Service(ParentAbstractClass clazz) {
this.clazz = clazz;
}

public void process() {
clazz.method();
}
}

这是服务类,它具有要注入(inject)的类的抽象,并调用一个方法。

我的抽象类具有一些通用逻辑和一个抽象方法的特定于实现的代码。

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 的引用:

Due to the proxy-based nature of Spring’s AOP framework, calls within the target object are, by definition, not intercepted. For JDK proxies, only public interface method calls on the proxy can be intercepted. With CGLIB, public and protected method calls on the proxy are intercepted (and even package-visible methods, if necessary). However, common interactions through proxies should always be designed through public signatures.

Note that pointcut definitions are generally matched against any intercepted method. If a pointcut is strictly meant to be public-only, even in a CGLIB proxy scenario with potential non-public interactions through proxies, it needs to be defined accordingly.

If your interception needs include method calls or even constructors within the target class, consider the use of Spring-driven native AspectJ weaving instead of Spring’s proxy-based AOP framework. This constitutes a different mode of AOP usage with different characteristics, so be sure to make yourself familiar with weaving before making a decision.

所以你有两种可能的方法来解决这个问题:

  1. 仅在其他 bean 调用的方法上使用您的方面(无自调用)
  2. 使用AspectJ AOP实现。我准备了一个使用 AspectJ 编译时编织的简单示例,代码托管在 github
<小时/>

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>

关于java - 如何为抽象方法创建切入点,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54536039/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com