上下文:我想在Spring Boot中创建一个自定义注释,并为处理添加额外的逻辑。我举了一个注释非常简单的例子,但我希望有几个这样的注释具有更细粒度的控制。
解决这个问题有几种方法:
我必须使用最新的一个,因为上面两个不适用于我的用例。
问题:
我在静态编程语言中有一个自定义注释,我希望它被注册并在运行时被检查。
@Retention(AnnotationRetention.RUNTIME)
@Target(AnnotationTarget.FUNCTION)
annotation class OfflineProcessing(val allow: Bool)
REST控制器如下:
@RestController
class ApiController {
@GetMapping("/api/version")
@OfflineProcessing(true)
fun apiVersion(): String {
return "0.1.0"
}
}
其思想是每个方法都有注释,并根据线性处理的允许与否,生成条件逻辑。
我已经尝试过创建基本的
PostBean处理机
:
@Component
class OfflineProcessingAnnotationProcessor @Autowired constructor(
val configurableBeanFactory: ConfigurableListableBeanFactory
) : BeanPostProcessor {
@Throws(BeansException::class)
override fun postProcessBeforeInitialization(bean: Any, beanName: String): Any? {
println("Before processor. Bean name: $beanName, Bean: $bean. Bean factory: $configurableBeanFactory.")
return super.postProcessBeforeInitialization(bean, beanName)
}
@Throws(BeansException::class)
override fun postProcessAfterInitialization(bean: Any, beanName: String): Any? {
println("After processor. Bean name: $beanName, Bean: $bean. Bean factory: $configurableBeanFactory.")
return super.postProcessAfterInitialization(bean, beanName)
}
}
很明显,注释不会在BeanPost处理机的其他注释中被记录,我混淆了如何访问它,到目前为止,我没有找到任何其他没有BeanPost处理机的好例子。
依赖性:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
</dependency>
我做错什么了吗?还是我试图用错误的方法来完成任务?
这是一个一般性的问题,不是科特林特有的。
我认为,你试图解决这个问题的误解是,你在使用BeanPostProcessor。bean是在早期阶段创建的,它可能是一个单例,因此在执行rest请求时不会调用它。这意味着您需要检查一个包含注释的bean,然后在其上创建一个代理bean,并将您的逻辑嵌入到该代理中。
这与AOP的做法非常相似,@eol的方法是匹配复活节。
我想建议使用拦截器,但不是bean创建拦截器。
我的答案是受Spring Boot添加Http请求拦截器的启发
定义注释
@Retention(AnnotationRetention.RUNTIME)
@Target(AnnotationTarget.FUNCTION)
annotation class OfflineProcessing(val allow: Boolean)
定义拦截器
@Component
class CustomRestAnnotationInterceptor:HandlerInterceptor {
private val logger: Logger = LoggerFactory.getLogger(this.javaClass)
override fun preHandle(request: HttpServletRequest, response: HttpServletResponse, handler: Any): Boolean {
if (handler is HandlerMethod) {
var isOffline: OfflineProcessing? = handler.getMethodAnnotation(OfflineProcessing::class.java)
if (null == isOffline) {
isOffline = handler.method.declaringClass
.getAnnotation(OfflineProcessing::class.java)
}
if (null != isOffline) {
logger.info("method called has OfflineProcessing annotation with allow=${isOffline.allow}" )
}
}
return true
}
}
将拦截器添加到路径
@Configuration
class WebConfig : WebMvcConfigurer {
@Autowired
lateinit var customRestAnnotationInterceptor: CustomRestAnnotationInterceptor
override fun addInterceptors(registry: InterceptorRegistry) {
// Custom interceptor, add intercept path and exclude intercept path
registry.addInterceptor(customRestAnnotationInterceptor).addPathPatterns("/**")
}
}
使用控制器上的注释
日志会显示
2022-04-14 08:48:58.785 INFO 32595 --- [nio-8080-exec-1] .h.s.k.q.CustomRestAnnotationInterceptor : method called has OfflineProcessing annotation with allow=true
这不是对你的问题的直接回答,但是在这种情况下,我只是简单地使用Spring AOP,而不是实现BeanPost处理机。要做到这一点,您可以定义以下注释和相应的方面,例如:
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
annotation class OfflineProcessing(val allowed: Boolean = true)
@Aspect
@Component
class OfflineProcessingAspect {
@Pointcut("@annotation(<path.to.annotation.package>.OfflineProcessing)")
fun offlineProcessingPointcut(offlineProcessing: OfflineProcessing?) {
}
@Around("offlineProcessingPointcut(offlineProcessing)")
@Throws(Throwable::class)
fun around(pjp: ProceedingJoinPoint, offlineProcessing: OfflineProcessing): Object {
if (offlineProcessing.allowed()) {
// your pre-processing logic here
val result = pjp.proceed()
// post-processing logic here
return result
}
// do the same for non-allowed offline-processing ...
}
}
最后,添加以下依赖项:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
我有以下问题:-创建了几个模块来实现类,并用-我的Android应用程序正在使用检索这些类。但是由于某种原因,没有在
我试图转换一些使用Jackson的@JsonSubTypes注释来管理多态性的Java代码。 以下是可用的Java代码: 以下是我认为等效的Kotlin代码: 但我在三行“JsonSubTypes.Type”中的每一行都会出现以下错误: 知道吗?
暴露0.27.1是否能够翻译以下SQL语句? 下面是我尝试的内容,但不幸的是,子查询独立于查询的其余部分工作。 此外,如果可能的话,那么如何使用别名从ResultRow获取结果?在这个示例之后,解决方案似乎是将整个子查询存储在单个变量中,并使用一个alias()方法调用,但这看起来很难看。有没有更好的方法?
我使用以下方法将KSP与Room结合使用: 这确实有效。但是,当我尝试运行它时,我会收到此警告 [ksp]我的数据库。kt:11:Schema导出目录未提供给注释处理器,因此无法导出架构。您可以提供注释处理器参数或将exportSchema设置为false。 为此:在使用KSP时,如何提供注释处理器参数?
为了描述Gradle构建脚本,我们可以通过< code>build.gradle.kts文件使用Kotlin。在< code>dependencies和build 部分全局定义要使用的Kotlin版本是一个常见的问题(在给定的情况下使用不同的版本是相当罕见的)。 请考虑以下代码 (Gradle 4.3.1): 如您所见,kotlin(在本例中为1.2.30)定义了两次:和,它们通常没有区别。由于D
我正在学习静态编程语言,我在函数方面有一些问题。我试图创建一个带有通用参数的函数接口。Java我会创建这样的东西: 然后我可以在其他地方像这样使用它(给定扩展: 你是怎么和Kotlin写这篇文章的? 我尝试的第一件事是使用如下类型别名: 但是,当我将绑定添加到type参数时,它停止了工作: 第二种方法是编写一个扩展函数类型的接口: 然而,现在我不知道如何用这个来实例化lambda函数。当我从中创建