1548 字
8 分钟
Java注解

Java Annotation(注解)#

  • java jdk5.0 引入的一种元数据。它本身不影响代码逻辑

  • 可以用于标记、说明、配置,结合反射实现功能

  • 常用注解:

    • @Override

    • @Deprecated

核心概念#

什么是注解#

注解是代码的标签或标记,可以附加在类、方法、属性、构造器、包、方法参数…

它不是代码本身,不直接执行逻辑

它可以被编译器、jvm、框架读取并解析

注解本质:注解就是一个特殊的接口

核心原理#

注解本质#

注解在Java语言中,本质是:

public interface MyAnnotation extends Annotation{
//注解内容
}
public @interface MyAnnotation{
//注解内容
}

生命周期(@Retention)#

RetentionPolicy.SOURCE:仅限源码阶段,编译后丢弃

RetentionPolicy.CLASS:编译到class字节码文件中,但JVM运行时不加载

RetentionPolicy.RUNTIME:运行时保留,可以通过反射读取

作用目标(@Target)#

ElementType.TYPE:类、接口、枚举

ElementType.METHOD:方法

ElementType.FIELD:属性

ElementType.PARAMETER:方法参数

ElementType.CONSTRUCTOR:构造器ElementType.ANNOTATION_TYPE:注解本身

注解解析原理#

编译期解析:编译器读取注解,生成代码/校验

运行期解析:反射读取注解信息,动态执行逻辑

90%的框架都是靠反射+运行时注解实现功能

入门示例#

第一步:定义一个注解

//设置注解的生命周期(运行时注解)
@Retention(RetentionPolicy.RUNTIME)
//设置注解的作用目标(谁能用)
@Target({ElementType.TYPE,ElementType.METHOD})
public @interface MyAnntation {
String value() default "";
int age() default 18;
String[] tags() default {};
}

第二步:使用注解

@MyAnntation(value = "用户类",age = 20,tags = {"测试","业务"})
public class User {
@MyAnntation("打印方法")
public void print(){
System.out.println("执行print打印方法...");
}
}

第三步:反射+运行时注解(重点)

public class DemoTest {
public static void main(String[] args) throws NoSuchMethodException {
//1、获取User类的类实例
Class tClass=User.class;
//2、验证类实例的注解实例是否是MyAnntation.class
if(tClass.isAnnotationPresent(MyAnntation.class)){
MyAnntation myAnntation = (MyAnntation)
tClass.getAnnotation(MyAnntation.class);
System.out.println("value值:"+myAnntation.value());
System.out.println("age值:"+myAnntation.age());
System.out.println("tags值:"+ Arrays.toString(myAnntation.tags()));
Method method = tClass.getMethod("print");
MyAnntation annotation = method.getAnnotation(MyAnntation.class);
System.out.println("方法注解数据:"+annotation.value());
}
}
}

小结

注解不会对类业务逻辑进行个修改 常用的注解形式:运行时注解 本质:对类添加额外的数据信息,通过额外的数据信息进行业务操作

自定义权限校验(模拟 Spring Security)#

场景说明:接口需要登录/管理员权限才能访问,用注解统一控制

第一步:定义权限注解

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface RequirePermission {
//需要的权限字符串
String value();
}

第二步:定义业务接口

public class OrderService {
//管理员才能删除订单
@RequirePermission("order:delete")
public void deleteOrder(Long id){
System.out.println("删除订单:"+id);
}
}

第三步:拦截器解析权限

public class PermissionInterceptor {
//模拟当前用户权限
private static String currentUserPermission="order:delete1";
public static void invodeMethod(Object object, Method method) throws
InvocationTargetException, IllegalAccessException {
//检查方法是否有权限注解
if(method.isAnnotationPresent(RequirePermission.class)){
RequirePermission anno = method.getAnnotation(RequirePermission.class);
String needPermission= anno.value();
//判断权限
if(!needPermission.equals(currentUserPermission))
throw new RuntimeException("权限不足,需要:"+needPermission+",的权限");
method.invoke(object,10L);
}
}
public static void main(String[] args) throws NoSuchMethodException,
InvocationTargetException, IllegalAccessException {
OrderService orderService = new OrderService();
Method method = orderService.getClass().getMethod("deleteOrder", Long.class);
invodeMethod(orderService,method);
}
}

Java注解操作JDBC#

核心思路:自定义注解标签说明数据库信息(表名、字段名、主键),通过反射+注解,自动封装SQL,完成对数据库的操作

整体结构#

自定义表注解、字段注解

实体类绑定注解映射数据表信息

通过JDBC工具类,读取注解并拼接SQL

测试增删查的业务

自定义映射注解#

表名注解#

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface Table {
String value();
}

字段注解#

@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Column {
String value();
}

数据库实体类绑定注解#

@Table("book")
public class MyBook {
@Column("id")
private Integer book_id;
@Column("isbn")
private Integer book_isbn;
@Column("name")
private String book_name;
@Column("price")
private Integer book_price;
//无参、有参构造器...
//setter、getter方法...
//toString方法...
}

JDBC连接工具#

public class DBUtil {
private static Connection conn;
static {
try {
Class.forName("com.mysql.cj.jdbc.Driver");
conn = DriverManager.getConnection(
"jdbc:mysql://localhost:3306/java2506",
"root",
"1234"
);
} catch (ClassNotFoundException e) {
throw new RuntimeException(e);
} catch (SQLException e) {
throw new RuntimeException(e);
}
}
public static Connection getConnection(){
return conn;
}
}

注解解析+通用JDBC工具#

核心思路:读取类上@Table、属性上@Column,自动拼接SQL命令

import com.mysql.cj.xdevapi.Table;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
public class AnnoJdbcUtil {
public static int insert(Object entity) throws IllegalAccessException {
//获取实体类的类实例
Class tClass = entity.getClass();
//读取数据表名称
Table table = (Table) tClass.getAnnotation(Table.class);
//获取类实例注解(表名)
String tableName = table.value();
//获取所有属性实例对象
Field[] fields = tClass.getDeclaredFields();
//创建存储字段名称和对应数据的集合(必须是有序集合)
List<String> columns = new ArrayList<>();
List<Object> values = new ArrayList<>();
//循环所有属性实例对象
for (Field field : fields) {
Column column = field.getAnnotation(Column.class);
//如果属性实例对象没有注解,则跳过
if (column == null) continue;
//存储注解中的数据表字段名称
columns.add(column.value());
//解保护私有属性成员
field.setAccessible(true);
//存储私有属性成员数据
values.add(field.get(entity));
}
//拼接SQL命令( insert into 表名(字段1,字段2,...,字段N) values(值1,值2,...,值N))
String cols = String.join(",", columns);
StringBuffer placeholder = new StringBuffer();
for (int i = 0; i < columns.size(); i++) {
placeholder.append("?");
if (i != columns.size() - 1) placeholder.append(",");
}
String sql = "insert into " + tableName + "(" + cols + ") values("+placeholder+") "; System.out.println("
拼接SQL命令:
"+sql); //执行JDBC try(PreparedStatement ps = DBUtil.getConnection().prepareStatement(sql)){
for (int i = 0; i < values.size(); i++) {
ps.setObject(i + 1, values.get(i));
}
return ps.executeUpdate();
} catch(SQLException e){
throw new RuntimeException(e);
}
}
public static <T> T getById(Class<T> tClass, Integer id) {
Table tableAnno = tClass.getAnnotation(Table.class);
String tableName = tableAnno.value();
Field[] fields = tClass.getDeclaredFields();
//拼接SQL查询命令(select id,isbn,name,price from book where id=10)
StringBuffer sqlCols = new StringBuffer();
String primaryCol = null;
for (Field field : fields) {
Column colAnno = field.getAnnotation(Column.class);
if (colAnno == null) continue;
sqlCols.append(colAnno.value()).append(",");
//根据id主键查询数据
if ("id".equals(colAnno.value())) primaryCol = colAnno.value();
}
String selectSql = sqlCols.substring(0, sqlCols.length() - 1);
String sql = "select " + selectSql + " from " + tableName + " where " + primaryCol + "=?";
try (PreparedStatement ps = DBUtil.getConnection().prepareStatement(sql)) {
ps.setObject(1, id);
ResultSet rs = ps.executeQuery();
T entity = null;
if (rs.next()) {
entity = tClass.newInstance();
//反射赋值
for (Field field : fields) {
Column colAnno = field.getAnnotation(Column.class);
if (colAnno == null) continue;
field.setAccessible(true);
field.set(entity, rs.getObject(colAnno.value()));
}
}
return entity;
} catch (SQLException e) {
throw new RuntimeException(e);
} catch (InstantiationException e) {
throw new RuntimeException(e);
} catch (IllegalAccessException e) {
throw new RuntimeException(e);
}
}
}

测试调用#

public class JdbcAnnoTest {
public static void main(String[] args) throws IllegalAccessException {
MyBook myBook1 = new MyBook(6,1006,"Java 反射与注解程序设计",66);
int row = AnnoJdbcUtil.insert(myBook1);
System.out.println("受影响行:"+row);
MyBook myBook2 = AnnoJdbcUtil.getById(MyBook.class,6);
System.out.println("查询结果:"+myBook2);
}
}
Java注解
https://mizuki.mysqil.com/posts/5注解/
作者
SuifengFlying
发布于
2026-07-28
许可协议
CC BY-NC-SA 4.0

MySQL基础

5 / 5

Related articles

部分信息可能已经过时

封面
示例歌曲
示例艺术家
封面
示例歌曲
示例艺术家
0:00 / 0:00