spring boot isAnnotationPresent注解 加上@Retention(RetentionPolicy.RUNTIME) 也无效 @Target使用的是ElementType.FIELD
时间: 2024-03-09 11:04:59 浏览: 110
如果你的注解`@Retention`为`RUNTIME`,`@Target`指定了`ElementType.FIELD`,但是`isAnnotationPresent`仍然无法获取到注解信息,那么可能的原因有以下几个:
1. 注解定义的时候忘记添加`@Retention(RetentionPolicy.RUNTIME)`或`@Target(ElementType.FIELD)`元注解,或者注解定义的方式有误,导致无法正确解析注解。
2. 访问的目标对象或者目标属性不是在运行时被加载的,导致注解信息无法被正确解析。可以检查一下目标对象是否已经被正确地加载到内存中。
3. 如果目标对象是通过反射机制动态生成的,那么需要使用反射获取注解信息。具体可以参考以下代码:
```java
Field field = obj.getClass().getDeclaredField(fieldName);
Annotation annotation = field.getAnnotation(MyAnnotation.class);
if (annotation != null) {
// 注解存在
} else {
// 注解不存在
}
```
其中,`obj`为目标对象,`fieldName`为目标属性名,`MyAnnotation`为自定义注解。使用`getDeclaredField`方法获取目标属性,再使用`getAnnotation`方法获取注解信息。如果返回值不为`null`,则表示注解存在。
相关问题
spring boot自定义注解 传参接参
### 创建和使用带参数的自定义注解
在Spring Boot中创建并使用带有参数的自定义注解涉及几个关键步骤。这些步骤包括定义注解、配置组件扫描以及利用AOP或其他方式处理注解逻辑。
#### 定义自定义注解
首先,需要定义一个新的注解类,并指定其元数据属性。这可以通过`@interface`关键字完成。为了使该注解能够携带参数,可以在定义时声明相应的成员变量。下面展示了一个简单的例子:
```java
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
// 设置注解的作用范围为目标方法或字段级别
@Target({ ElementType.METHOD, ElementType.FIELD })
// 设定注解保留策略为运行时可见
@Retention(RetentionPolicy.RUNTIME)
public @interface CustomAnnotation {
// 注解可以接受字符串类型的参数,默认为空串
String value() default "";
}
```
此部分展示了如何定义一个名为`CustomAnnotation`的简单注解,它可以应用于方法或字段上,并允许传入一个可选的字符串参数[^1]。
#### 处理自定义注解
一旦定义好了注解,下一步就是决定在哪里以及怎样去读取这个注解的信息。对于大多数场景来说,最常用的方法之一是借助于面向切面编程(AOP),即通过编写AspectJ风格的切面来拦截被标记了特定注解的目标对象/行为。
这里给出一段基于AOP实现的例子,用于捕获任何带有上述自定义注解的方法调用,并打印出所附带的消息内容:
```java
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.stereotype.Component;
@Component
@Aspect
public class AnnotationProcessor {
@Before("@annotation(customAnnotation)")
public void process(JoinPoint joinPoint, CustomAnnotation customAnnotation){
System.out.println("Intercepted method call with message: "
+ customAnnotation.value());
}
}
```
这段代码实现了对所有标注有`CustomAnnotation`的地方进行前置增强(`@Before`)的功能,每当匹配到这样的地方就会触发相应的行为——在这里是指向控制台输出一条信息[^2]。
#### 应用实例
最后一步是在实际业务逻辑里运用之前准备好的工具。比如在一个控制器(Controller)内部添加这样一个注解,并为其提供具体的参数值:
```java
@RestController
@RequestMapping("/example")
public class ExampleController {
@CustomAnnotation(value="This is a test.")
@GetMapping("/test")
public ResponseEntity<String> getTest(){
return new ResponseEntity<>("Success", HttpStatus.OK);
}
}
```
当访问路径 `/example/test` 时,除了正常的HTTP响应外,还会看到由前面提到的那个方面程序产生的额外日志条目,显示了来自注解内的消息文本[^4]。
2.熟悉online代码生成,实现单表,父子表结构,不同数据字段如何界面配置,通过代码生成器生成不同风格的前端风格代码 3.对代码生成生成的代码,必须理解熟悉,了解代码规范,未来可能在这个基础上进行二次开发,对代码可以方便删除、补充 4.熟悉数据字典,包含注解@Dict; 5.熟悉redis缓存的使用,包含注解@Cacheable,@CacheEvict 6.系统权限用法需熟悉 7、学习和熟悉前端案例代码 三、考核要求 1.完成前端后端系统搭建 2.通过online构建父表:Customer(客户);子表:Order(订单)包含 订单金额,订单日期,丰满更多的字段元素,生成导出代码 3.在这个生成代码基础上,完成一个更加完整的功能,包含更复杂的多查询,补充权限功能,实现不同给用户看到不同的功能,查询到不同的内容 这些是前端还是后端的学习内容
### 单表和父子表界面配置
代码生成器的核心功能之一是对数据库中的单表和父子表结构进行快速的界面配置。对于单表,通常可以通过简单的字段映射完成界面设计;而对于父子表(如 `Customer` 和 `Order`),则需要考虑关联关系及其展示方式。
#### 配置方法
- **单表配置**
对于单表,代码生成器会读取数据库元数据并自动生成对应的模型类、控制器和服务接口。通过图形化界面或 YAML/JSON 文件指定字段显示名称、验证规则和其他 UI 属性[^1]。
- **父子表配置**
子父表的关系可通过外键约束自动识别,并在生成的界面上体现为嵌套表格或下拉框等形式。例如,在 `Order` 表中添加一个 `CustomerID` 字段作为外键,则可以在前端页面上提供一个选择客户的下拉菜单[^2]。
```java
@Entity
public class Order {
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "customerId", nullable = false)
private Customer customer;
}
```
---
### 前端风格代码生成与二次开发
为了满足不同项目的需求,代码生成器应支持多种主流前端框架样式(如 Vue.js、React 或 Angular)。以下是具体实现:
#### 多种前端风格的支持
- 使用模板引擎(如 Thymeleaf 或 FreeMarker)预设不同的组件库主题(Ant Design、ElementUI 等)。
- 用户可以选择目标框架后,生成器将替换默认模板文件以适配所选样式[^3]。
#### 二次开发技巧
- 提供可扩展的插件机制允许开发者修改生成逻辑。
- 支持热更新模式以便实时查看更改效果。
```javascript
// 示例:Vue 组件动态加载
<template>
<el-table :data="orders">
<el-table-column prop="orderId" label="订单编号"></el-table-column>
<el-table-column prop="customer.name" label="客户姓名"></el-table-column>
</el-table>
</template>
<script>
export default {
data() {
return { orders: [] };
},
};
</script>
```
---
### 数据字典 (@Dict)
数据字典用于简化枚举类型的管理和维护。它通常由注解驱动,减少硬编码带来的错误风险。
#### 实现细节
- 定义全局字典存储位置并通过 API 动态加载。
- 利用 Spring Boot 的 AOP 特性拦截请求参数转换成实际值。
```java
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Dict {
String type();
}
@Service
public class DictService {
public String getLabel(String type, Integer value) {
// 查询 DB 并返回对应标签名
}
}
```
---
### Redis 缓存 ( @Cacheable / @CacheEvict )
Redis 是高性能分布式内存对象缓存系统,常用来加速频繁访问的数据操作。
#### 注解说明
- `@Cacheable`: 将函数结果保存至缓存中,下次调用相同输入时直接返回缓存内容而不执行原方法体。
- `@CacheEvict`: 清除特定条件下的缓存条目。
```java
@Cacheable(value = "customers", key = "#id")
public Optional<Customer> findById(Long id) {}
@Transactional
@CacheEvict(value = "customers", allEntries = true)
public void deleteById(Long id) {}
```
---
### 权限管理系统
权限管理是企业级应用的重要组成部分,确保只有授权用户才能访问敏感资源。
#### 关键技术点
- RBAC 模型(角色基於權限控制)
- JWT Token 认证流程集成 OAuth2.0 标准协议。
```yaml
spring:
security:
oauth2:
resourceserver:
jwt:
jwk-set-uri: https://auth-server/.well-known/jwks.json
```
---
### 整体架构搭建
构建完整的前后端分离体系需综合运用微服务设计理念和技术栈如下:
- 后端采用 Spring Cloud 微服务体系配合 MyBatis Plus 快速持久层开发工具包;
- 前端选用 Vite 构建现代化 SPA 应用程序同时引入 Pinia 替代 Vuex 进行状态管理。
---
阅读全文
相关推荐















