1. OperationType.java
public enum OperationType {
INSERT,
UPDATE
}
- 功能:这是一个枚举类,定义了两种操作类型:
INSERT
(插入)和UPDATE
(更新)。在后续代码中,用于指定在哪些操作下进行自动填充。
2. AutoFillAnnotation.java
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
// 定义注解的作用目标为字段
@Target(ElementType.FIELD)
// 定义注解的保留策略为运行时
@Retention(RetentionPolicy.RUNTIME)
public @interface AutoFill {
// 注解的属性,默认值为空字符串
String value() default "";
// 新增 operationType 属性,指定在哪些操作类型下进行自动填充
OperationType[] operationType() default {OperationType.INSERT, OperationType.UPDATE};
}
@Target(ElementType.FIELD)
:表明@AutoFill
注解只能应用于类的字段上。@Retention(RetentionPolicy.RUNTIME)
:意味着该注解在运行时可通过反射机制获取,这样才能在程序运行过程中对其进行处理。String value() default "";
:定义了一个名为value
的属性,默认值为空字符串。这个属性可用于指定字段自动填充的值。OperationType[] operationType() default {OperationType.INSERT, OperationType.UPDATE};
:定义了一个OperationType
数组类型的属性operationType
,默认值包含INSERT
和UPDATE
两种操作类型。该属性用于指定在哪些操作类型下对标记的字段进行自动填充。
3. User.java
// 示例类,使用 @AutoFill 注解
class User {
@AutoFill(value = "John Doe", operationType = {OperationType.INSERT, OperationType.UPDATE})
private String name;
@AutoFill(value = "123 Main St", operationType = {OperationType.INSERT})
private String address;
public String getName() {
return name;
}
public String getAddress() {
return address;
}
}
- 这是一个示例类,展示了如何使用
@AutoFill
注解。 name
字段被@AutoFill
注解标记,指定了填充值为"John Doe"
,并且在INSERT
和UPDATE
操作时都进行填充。address
字段也被@AutoFill
注解标记,填充值为"123 Main St"
,但仅在INSERT
操作时进行填充。
4. AutoFillAspect.java
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;
import java.lang.reflect.Field;
@Aspect
@Component
public class AutoFillAspect {
// 定义切入点,这里假设标记了 @AutoFillMethod 的方法需要进行切入
@Pointcut("@annotation(com.example.demo.AutoFillMethod)")
public void autoFillMethods() {}
@Before("autoFillMethods() && args(operationType, obj)")
public void beforeAutoFillMethods(JoinPoint joinPoint, OperationType operationType, Object obj) throws IllegalAccessException {
Class<?> clazz = obj.getClass();
Field[] fields = clazz.getDeclaredFields();
for (Field field : fields) {
if (field.isAnnotationPresent(AutoFill.class)) {
AutoFill autoFill = field.getAnnotation(AutoFill.class);
for (OperationType op : autoFill.operationType()) {
if (op == operationType) {
field.setAccessible(true);
field.set(obj, autoFill.value());
break;
}
}
}
}
}
}
@Aspect
和@Component
:@Aspect
注解表明这是一个切面类,@Component
注解将该类作为 Spring 组件进行管理。@Pointcut("@annotation(com.example.demo.AutoFillMethod)")
:定义了一个切入点,该切入点匹配所有标记了@AutoFillMethod
注解的方法。@Before("autoFillMethods() && args(operationType, obj)")
:这是一个前置通知,在切入点方法执行之前执行。它要求切入点方法的参数必须包含OperationType
类型的operationType
和一个对象obj
。- 方法体:
- 获取对象的类信息和所有声明的字段。
- 遍历所有字段,检查是否标记了
@AutoFill
注解。 - 如果标记了
@AutoFill
注解,则获取注解的operationType
属性,并检查当前操作类型是否匹配。 - 如果匹配,则将注解的
value
属性值赋给该字段。
5. AutoFillMethod.java
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface AutoFillMethod {
}
- 这是一个自定义注解,用于标记哪些方法需要被 AOP 切面切入。
@Target(ElementType.METHOD)
表示该注解只能应用于方法上,@Retention(RetentionPolicy.RUNTIME)
表示在运行时可通过反射获取该注解。
6. UserService.java
UserService.java
import org.springframework.stereotype.Service;
@Service
public class UserService {
@AutoFillMethod
public void saveUser(OperationType operationType, User user) {
System.out.println("Saving user: " + user.getName() + ", " + user.getAddress());
}
}
@Service
注解将该类作为 Spring 服务组件进行管理。saveUser
方法被@AutoFillMethod
注解标记,因此在调用该方法时,AutoFillAspect
类中的前置通知会先执行,对User
对象的相应字段进行自动填充。
7. MainApp.java
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class MainApp implements CommandLineRunner {
@Autowired
private UserService userService;
public static void main(String[] args) {
SpringApplication.run(MainApp.class, args);
}
@Override
public void run(String... args) throws Exception {
User user = new User();
OperationType operationType = OperationType.INSERT;
userService.saveUser(operationType, user);
}
}
@SpringBootApplication
是 Spring Boot 应用的核心注解,用于启用自动配置、组件扫描等功能。- 实现
CommandLineRunner
接口,重写run
方法,在 Spring Boot 应用启动后执行该方法。 - 在
run
方法中,创建一个User
对象和一个OperationType
对象,然后调用UserService
的saveUser
方法,触发 AOP 切面的前置通知,对User
对象的字段进行自动填充。