如果程序员返回的是Arraylist而不是List,我会尝试生成一个警告。我使用Spring Boot,Spring Data JPA。
Pojo示例
@Entity
public class Box {
@Id
@GeneratedValue
private long id;
private long prio;
public long getPrio() {
return prio;
}
public void setPrio(long prio) {
this.prio = prio;
}
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
}
我的存储库:
@Repository
public interface BoxRepository extends JpaRepository<Box, Long>{
public List findByPrio(long prio);
}
@Aspect
@Component
public class ReturnList {
@AfterReturning(value = "within(de.fhb.*) && !within(org.springframework.*) && call(* de.fhb..*(..))", returning = "returnValue")
public void logServiceAccess(JoinPoint joinPoint, Object returnValue) {
if (returnValue != null) {
if (returnValue.getClass() != null) {
Class<?> clazz = returnValue.getClass();
if (java.util.List.class.isAssignableFrom(clazz)) {
System.out
.println("Please use List instead of a concrete implementation ( "+ returnValue.getClass() + " ) for method: "
+ joinPoint.getSignature().getName() + ".");
}
}
}
}
}
System.out.println(boxRepository.findByPrio(1));
首先,list.class.isAssignableFrom(clazz)
对于List
和ArrayList
都是真的,也就是说,您不能像这样区分这两者。顺便说一句,returnvalue.getclass()
永远不会计算为list
,因为这是一种接口类型。它将始终根据实际的实现类进行计算,例如ArrayList
。因此,你试图通过反思找出你想知道的东西的人为方式注定要失败。
好消息是:AspectJ使您能够做您想做的事情。您似乎通过加载或编译时编织来使用真正的AspectJ,否则您不能使用call()
切入点,因为它在Spring AOP中不可用。编辑:是的,您的Gradle构建显示您正在使用编译时编织。但是,为什么要在当前版本1.8.4中使用编译器,而在非常过时的1.5.4中使用AspectJ运行时呢?您应该协调两者,并在版本1.8.4中使用aspectjrt。
现在让我们来解构你的切入点:
within(de.fhb.*) &&
!within(org.springframework.*) &&
call(* de.fhb..*(..))
您真正想要了解的是,在您自己的包中是否有返回具体类型的方法,如ArrayList
,而不是接口类型List
。正确?我认为切入点应该是这样的:
within(de.fhb..*) &&
execution(java.util.List+ *(..)) &&
!execution(java.util.List *(..))
它意味着:对于de.fhb
或其子包中的所有类,根据其方法签名拦截返回列表+
的所有方法(+
意味着:列表
或其子类型)。因为这也会匹配返回父类型list
的方法,而您只需要子类型,所以必须通过!execution(java.util.list*(..))
在切入点的第三部分排除该类型。
我匹配方法执行而不是调用,因为这样更有效。如果从包中的100个地方调用一个方法,call()
将把方面代码编织到100个调用连接点中,而execution()
实际上只是编织方法实际定义的地方。
下面是一些示例代码:
驱动程序应用程序:
您可以看到,有一个方法正确地声明了List
返回类型,而其他方法则声明了“禁止的”返回类型,如ArrayList
、LinkedList
和Vector
。
package de.fhb.app;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.Vector;
public class Application {
public static List<String> methodReturningList() {
return new ArrayList<String>();
}
public static ArrayList<String> methodReturningArrayList() {
return new ArrayList<String>();
}
public static LinkedList<String> methodReturningLinkedList() {
return new LinkedList<String>();
}
public static Vector<String> methodReturningVector() {
return new Vector<String>();
}
public static void main(String[] args) {
methodReturningList();
methodReturningArrayList();
methodReturningLinkedList();
methodReturningVector();
}
}
package de.fhb.aspect;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
@Aspect
public class ReturnTypeChecker {
@AfterReturning("within(de.fhb..*) && execution(java.util.List+ *(..)) && !execution(java.util.List *(..))")
public void logServiceAccess(JoinPoint thisJoinPoint) {
System.out.println(thisJoinPoint);
}
}
execution(ArrayList de.fhb.app.Application.methodReturningArrayList())
execution(LinkedList de.fhb.app.Application.methodReturningLinkedList())
execution(Vector de.fhb.app.Application.methodReturningVector())
类型检查方面,变体B(编译时检查):
但是AspectJ可以做得更多。为什么不在编译过程中抛出警告甚至错误,即在软件打包和部署之前?您的开发团队可以在bug进入生产代码之前修复它们。为此,请使用@DeclareWarning
或@DeclareError
:
package de.fhb.aspect;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.DeclareError;
@Aspect
public class ReturnTypeChecker {
@DeclareError("within(de.fhb..*) && execution(java.util.List+ *(..)) && !execution(java.util.List *(..))")
private static final String typeWarning = "Please do not declare methods returning concrete subclasses of List";
}
现在您将在控制台上得到编译错误。在Eclipse中,它如下所示:
我在一个名为seedrecord的对象和一个名为FielliateLink的对象之间有一个manytomany关系。为了删除FielliateLink,我需要首先从每个SeedRecord的FielliateList中删除对它的引用。之后,我使用spring JParepository的delete方法删除对象。因为我的服务(FiniliateLinkService)中有不同的删除方法,所以我决定
我想在try块中捕获PyCharm的stop信号(当stop被按下时),但是我不知道这个信号是什么或者如何在代码中捕获它。JetBrains在他们的文档中没有提供这方面的见解。 我尝试将其捕获为,但它似乎根本不是异常。 这在编程上是完全可以捕获的吗?
问题内容: 我有一个文件需要读取,打印出整数,捕获异常并继续显示下一个整数,依此类推,直到不再有整数。 该文件包含:12 5 sd 67 4 cy 我希望它显示: 12 5 输入错误 67 4 输入错误 但是,它只给我12、5,后面是输入错误,然后停止。我尝试将所有内容放入while循环中,并且由于输入异常而无休止地循环。 我缺少什么,以便循环继续读取下一个int,依此类推? 问题答案: try
为了在生产环境中启动我的Spring Boot应用程序,我的公司有一个执行“java-jar”的系统,我试图在我的Intellij思想中模拟它,并且jar可以正确启动,我也可以用proyect源代码进行调试。 在运行和调试模式下,当我单击stop按钮时,jar突然停止,并显示消息: 并且我无法捕获关闭事件来关闭我的DB连接。我尝试了其他stackoverflow解决方案,如在Main中运行的Spr
我正在寻找一种方法来停止/杀死线程,我看到Thread.stop()已被弃用。所以我开始寻找另一个解决方案,并看到多个帖子建议这样做: 但这不会阻止我的线程,我的线程看起来像这样: 有人得到我可以用来停止/杀死我的线程的解决方案吗?非常感谢任何帮助。
当我从测试类调用functions方法时,我希望executeSol方法不要运行,因为它会导致错误。