我为某些日志目的创建了一个自定义注释。此注释应用于通过扩展JpaRepository在项目中创建的Spring jpa存储库。所以现在发生的是,对于read方法,它可以正常工作,但对于保存部分,永远不会调用@周围建议。以下是我的@周围建议
@Around("@within(com.myproject.annotations.RepoAware)")
public void log(final ProceedingJoinPoint jp){
return log(jp,true);
}
我的log方法是采用一个布尔参数,并以此为基础记录一些东西。以下是回购代码
@Repository
@RepoAware
public interface MyRepo extends JpaRepository<Student,Long>{
}
现在,当我调用不属于我的存储库MyRepo的repo方法时,比如save、saveAll或是存在于父层次结构中的方法,@Around建议就不起作用了。当我应用调试器时,我可以看到在保存调用期间,代理的类型是CrudRepository。所以当我在MyRepo中重写save方法时。类它开始工作。我对此感到困惑,因为MyRepo最终通过JpaRepository扩展了CrudRepository。请让我知道如何解决这个问题或我在这里做错了什么。
还提供有关如何在切入点中使用not表达式的帮助。比如上面的例子,我想定位我的所有存储库,除了有@RepoAware注释的。我创建了下面的建议,但它也不起作用。
@Around("target(org.springframework.data.jpa.repository.JpaRepository) and !@within(com.myproject.annotations.RepoAware)")
public Object logDBMetrics(final ProceedingJoinPoint pjp) throws Throwable {
return log(pjp,false);
}
对于具有@RepoAware注释的存储库,也会调用上述建议。
提前致谢!
我终于能够让它工作了,下面是我使用的方法。感谢@Andrey B. Panfilov。
我创建了一个由MyRepo扩展的标记接口,然后在我的周围建议中,我使用类类型来检查它是否可以从该接口分配。如果是,则使用true或false登录。
@Around("target(org.springframework.data.jpa.repository.JpaRepository)")
public void log(final ProceedingJoinPoint jp){
Class<?> clazz=MyRepoInterface.class;
return clazz.isAssignableFrom(pjp.getTarget().getClass())?log(jp,true):log(pjp,false);
}
----
@Repository
public interface MyRepo extends JpaRepository<Student,Long>,MyRepoInterface{
}
-----
public interface MyRepoInterface{}
对于某些切入点,spring aop的行为仍然未知。就像使用AND一样,NOT和表达式似乎不起作用。我尝试了上面提到的几种方法,但都没有奏效。
AspectJ在Spring基础结构的情况下具有非常有限的功能,但是可以通过顾问来实现您的要求(另请查看:使用@Bean的Java中的Spring顾问)
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD, ElementType.TYPE})
@Inherited
public @interface CustomRepositoryAnnotation {
}
@Component
public class CustomRepositoryAnnotationAdvisor extends AbstractPointcutAdvisor {
private static final Logger log = LoggerFactory.getLogger(CustomRepositoryAnnotationAdvisor.class);
private final Advice advice;
private final Pointcut pointcut;
public CustomRepositoryAnnotationAdvisor() {
this.advice = new MethodInterceptor() {
@Nullable
@Override
public Object invoke(@NonNull MethodInvocation invocation) throws Throwable {
log.info("DemoAnnotationAdvisor: {}", invocation.getMethod().getName());
return invocation.proceed();
}
};
this.pointcut = new AnnotationMatchingPointcut(CustomRepositoryAnnotation.class, null, true);
}
@Override
public Pointcut getPointcut() {
return pointcut;
}
@Override
public Advice getAdvice() {
return advice;
}
}
天然气水合物演示项目
更新。
对这个主题进行了一些研究,发现了一篇关于Spring和AspectJ切入点指示符的精彩文章
首先,@in
不应该在你的情况下工作(拦截超接口方法)-你应该使用@Target
,不幸的是@Target
切入点指示符似乎在Spring AOP
中被破坏:存在带有单个@target
切入点的建议会导致Spring为每个bean创建CGLIB代理,这是不可取的,甚至是不可能的(jdk类、最终类、没有公共构造函数的类等),尝试缩小建议的范围也失败了:例如Spring不应用建议@target(注释)
其次,在<代码>SpringAPO的情况下
如果您想避免运行时反射,那么Spring AOP方面的解决方案,即基于代理的Spring风格AOP框架,如下所示:
@Pointcut(
"execution(* (" +
"@com.example.accessingdatajpa.CustomRepositoryAnnotation " +
"org.springframework.data.repository.CrudRepository+" +
").*(..))"
)
这是针对目标
更新2:解决方案切入点的更简单、更通用的版本是:
@Pointcut("execution(* (@com.example.accessingdatajpa.CustomRepositoryAnnotation *..*).*(..))")
仅供参考,通常*
而不是*…*
应该作为AeyJ语法中“任何包中的任何类”的更简单替代品,但在这种情况下它似乎不起作用。
什么不起作用以及为什么:
更新1,回答评论中提出的问题:
< code > @ target(CustomRepositoryAnnotation)...-您是如何开始申请的?
通过排除我在这里的回答中描述的Spring包,并从JDK中排除最终类型,这些类型当然不能子类化,因此也不能被代理:
"@target(com.example.accessingdatajpa.CustomRepositoryAnnotation)"
+ " && !within(org.springframework..*) && !within(is(FinalType))"
但是在这种情况下,由于我上面解释的内容,切入点不匹配。
顺便说一句,它没有解释为什么目标(标记接口)
确实有效,似乎注释支持在Spring AOP中被破坏了。
不,它没有被破坏,只是你对实现注释接口的类继承注释的期望是错误的。
target(标记接口)
工作,因为运行时类型实现接口,因此切入点匹配。类继承与注释继承不同。无论喜欢与否,后者只存在于我链接的答案中解释的有限程度,并在@Inherited
javadoc中陈述。
我在整个代码中有一堆常量,用于系统的各种可调整属性。我正在将它们全部移动到一个中央文件中。我目前的解决方案是有一个静态加载文件并公开各种getter方法,如下所示: 唯一的问题是,对于我从这个文件中获得的每个常量,我都有一些样板: 我不认为我想使用Spring或类似的东西,因为那看起来更像是boilerplae。我希望使用自定义注释来解决这个问题。我找到了这个教程,但是我真的不能弄清楚如何从注释处
问题内容: 在ajax中使用base_url()从codeigniter项目中获取数据库。给定的base_url就像http://domainname.com。很好 如果我可以在地址栏中输入http://www.domainname.com之类的网址,则无法正常工作。该代码是 请帮助解决此问题。谢谢 问题答案: 我认为最好的解决方案是: 只需在HTML的标头部分中添加以下脚本即可。 然后在您的Aj
我目前正在用JavaFX做一个小项目。我使用SceneBuilder创建了我的GUI的第一个草图。它仍然需要一些调整和样式,但我想看看它是否工作到目前为止。 我在GUI上有两个超链接,如果用户单击其中一个,默认的系统浏览器将打开一个特定的URL。 到目前为止,我得到了这个: 主要的爪哇: 数据库。爪哇: 测试视图。爪哇: 在我的控制器中,我想将ActionHandler设置为超链接,但它不起作用,
我在textInputEditText中使用textInputLayout,我必须为editText设置背景,以实现editText的边框视图。但是当我调用textInputLayout上的setError()时,整个editText颜色将变为红色。但我只想更改错误文本的颜色,而不是整个视图。 设置前错误: 请帮帮我,我做错了什么?
如果Spring批处理作业业务逻辑出现ArrayIndexOutOfBoundsException,我必须从我的自定义映射器FieldSetMapper of reader FlatFileItemReader中跳过一个自定义异常(CSVFieldMappingException)。为此,我添加了作业步骤的配置,如下所示。 但这不起作用,因为每当我抛出自定义RunTimeException时,就会
问题内容: 注释如何与Java一起使用?以及如何创建这样的自定义注释: 基本上,我需要保留的POJO在持久化时像这样进行序列化: 这样,实际的生成/持久对象是这样的: 任何想法如何实现这一点? 问题答案: 如果创建自定义注释,则必须使用此处的 API 示例进行处理。您可以参考如何声明注释。 这是Java中的示例注释声明的样子。 并被称为。 表示您想在运行时保留注释,并且可以在运行时访问它。 表示您