嘿。
我正在写一个@Aspect 来记录我的持久层。
首先是一些可能向有经验的开发人员显示错误的代码;)
/** Interface of the class to observe. */
public interface PersistenceService {
public Serializable save(Serializable serializable);
public List<Serializable> save(List<Serializable> list)
}
/** Actual class to observe. */
@Service
public class PersistenceService {
@Autowired
private SomeJpaRepository rep;
public Serializable save(Serializable serializable) {
return rep.save(serializable);
}
public List<Serializable> save(List<Serializable> list) {
return rep.save(list);
}
}
这里的方面:
/** The Aspect. */
@Aspect
@Component
public class PersistenceService {
/** A org.slf4j.Logger (using logback). */
private final Logger logger = LoggerFactory.getLogger(getClass());
/** Pointcut to define the classes to observe. */
@Pointcut("within(de.mypckg.myproject.persistence.*.*)")
public void inPersistanceLayer() {}
/** Pointcut for the first save-method. */
@Pointcut("execution(public * save(..)) && args(serializable)")
public void saveOperation(Serializable serializable) {}
/** Pointcut for the first save-method. */
@Pointcut("execution(public * save(..)) && args(list)")
public void saveOperation(List<Serializable> list) {}
/** Method for the first save-method. */
@Around("inPersistanceLayer() && saveOperation(serializable)")
public List<Serializable> logSave(ProceedingJoinPoint joinPoint, Serializable serializable) throws Throwable {
// log some stuff
Object saved = joinPoint.proceed();
// log somemore stuff
}
/** Method for the second save-method. */
@Around("inPersistanceLayer() && saveOperation(list)")
public List<Serializable> logSave(ProceedingJoinPoint joinPoint, List<Serializable> list) throws Throwable {
// log some stuff
Object saved = joinPoint.proceed();
// log somemore stuff
}
}
如果我只有一个切入点(及其方法)它可以工作,但如果我添加第二个,我会得到以下异常:
java.lang.IllegalArgumentException: warning no match for this type name: list [Xlint:invalidAbsoluteTypeName]
我改变了切入点的顺序,它总是排在第二个。关于如何解决这个问题的任何想法?
更新
一旦我发布了问题,我就有了一个想法。我改变了这样的切入点:
/** The Aspect. */
@Aspect
@Component
public class PersistenceService {
/** A org.slf4j.Logger (using logback). */
private final Logger logger = LoggerFactory.getLogger(getClass());
/** Pointcut to define the classes to observe. */
@Pointcut("within(de.mypckg.myproject.persistence.*.*)")
public void inPersistanceLayer() {}
/** Pointcut for the save-method. */
@Pointcut("execution(public * save(..))")
public void saveOperation() {}
/** Pointcut for the serializable argument. */
@Pointcut("args(serializable)")
public void serializableArgument(Serializable serializable) {}
/** Pointcut for the list argument. */
@Pointcut("args(list)")
public void listArgument(List<Serializable> list) {}
/** Method for the first save-method. */
@Around("inPersistanceLayer() && saveOperation() && serializableArgument(serializable)")
public Object logSave(ProceedingJoinPoint joinPoint, Serializable serializable) throws Throwable {
// log some stuff
Object saved = joinPoint.proceed();
// log somemore stuff
return saved;
}
/** Method for the second save-method. */
@Around("inPersistanceLayer() && saveOperation(list) && listArgument(list)")
public Object logSave(ProceedingJoinPoint joinPoint, List<Serializable> list) throws Throwable {
// log some stuff
Object saved = joinPoint.proceed();
// log somemore stuff
return saved;
}
}
现在异常消失了,但还有一个小问题(我猜这更容易解决):由于 ArrayList 实现了 Serializable 两个切入点都被执行,至少在我使用 ArrayList 的测试用例中。
我将对此进行调查并发布我的发现,但也很感谢您的帮助;)
更新 2
更正了 kriegaex 声明的复制粘贴错误。谢谢!
logSave(..) 方法的返回类型是 Object。
更新 3
我将代码更改为仅使用一个切入点和一种方法,并使用 kriegaex 提议的 instanceof 进行检查。
/** The Aspect. */
@Aspect
@Component
public class PersistenceService {
/** A org.slf4j.Logger (using logback). */
private final Logger logger = LoggerFactory.getLogger(getClass());
/** Pointcut to define the classes to observe. */
@Pointcut("within(de.mypckg.myproject.persistence.*.*)")
public void inPersistanceLayer() {}
/** Pointcut for the save-method. */
@Pointcut("execution(public * save(*)) && args(serializable)")
public void saveOperation(Serializable serializable) {}
/** Method for the first save-method. */
@Around("inPersistanceLayer() && saveOperation() && serializableArgument(serializable)")
public Serializable logSave(ProceedingJoinPoint joinPoint, Serializable serializable) throws Throwable {
// log some stuff
Serializable saved = (Serializable) joinPoint.proceed();
if (saved instanceof List<?>) {
List<?> savedList = (List<?>) saved;
// log somemore stuff with a List
} else {
// log somemore stuff
}
return saved;
}
}
我仍然想知道为什么它不能以另一种方式工作。