《深入理解 Java 自带注解、Spring 注解及 Lombok 注解》

一、Java 自带注解

(一)基本注解

  1. @Override

    • 作用 :用于表示一个方法是重写父类或实现接口中的方法。这可以帮助开发者明确方法的意图,并且在编译时期检查方法是否正确地重写了父类或接口中的方法。

    • 示例

class Animal {
    public void eat() {
        System.out.println("动物吃饭");
    }
}
​
class Dog extends Animal {
    @Override
    public void eat() {
        System.out.println("狗吃饭");
    }
}

在这个例子中,Dog 类的 eat() 方法使用 @Override 注解,表明它是重写自 Animal 类的 eat() 方法。

  1. @Deprecated

    • 作用 :用于标记一个程序元素(如类、方法、字段等)已经过时。当使用被标记为过时的元素时,编译器会发出警告。这通常是因为有更好的替代方案,或者该元素可能在未来的版本中被删除。

    • 示例

@Deprecated
public class OldClass {
    public void oldMethod() {
        System.out.println("旧方法");
    }
}

当其他代码使用 OldClassoldMethod() 时,编译器会提示该类和方法已经过时。

  1. @SuppressWarnings

    • 作用 :用于抑制编译器警告。有时候代码可能会产生警告信息,但是开发者确认这些警告可以忽略,就可以使用这个注解来避免冗长的警告信息。

    • 常见参数

      • rawtypes :用于抑制未经检查的转换的警告。

      • unchecked :用于抑制未检查的操作的警告。

      • unused :用于抑制未使用的变量的警告。

    • 示例

@SuppressWarnings("rawtypes")
public class TestWarning {
    @SuppressWarnings("unused")
    public static void main(String[] args) {
        List list = new ArrayList();
        list.add("测试");
    }
}

在这个例子中,@SuppressWarnings("rawtypes") 用于抑制未经检查的转换警告,因为 List 应该是参数化的类型(如 List<String>),但这里使用了原始类型。

(二)元注解

元注解是用来定义其他注解的注解,它们主要用于框架或工具的开发。

  1. @Target

    • 作用 :用于指定注解可以应用的程序元素类型。

    • 常见参数

      • ElementType.TYPE :类、接口(包括注释类型)或枚举声明。

      • ElementType.FIELD :字段、枚举常量。

      • ElementType.METHOD :方法。

      • ElementType.PARAMETER :方法参数。

      • ElementType.CONSTRUCTOR :构造函数。

      • 还有其他类型的参数,如 ElementType.LOCAL_VARIABLE(局部变量)、ElementType.ANNOTATION_TYPE(注解类型)等。

    • 示例

@Target(ElementType.FIELD)
public @interface MyFieldAnnotation {
    String value();
}

这个自定义注解 @MyFieldAnnotation 只能应用在字段上。

  1. @Retention

    • 作用 :用于指定注解的生命周期。

    • 常见参数

      • RetentionPolicy.SOURCE :注解只保留在源代码中,编译时就会被忽略,不会写入到字节码文件中。

      • RetentionPolicy.CLASS :注解会被写入到字节码文件中,但在运行时会被虚拟机忽略,不能通过反射获取。

      • RetentionPolicy.RUNTIME :注解会被写入字节码文件中,并且可以在运行时通过反射获取。

    • 示例

@Retention(RetentionPolicy.RUNTIME)
public @interface MyRuntimeAnnotation {
    String value();
}

这个自定义注解 @MyRuntimeAnnotation 在运行时可以通过反射获取。

  1. @Documented

    • 作用 :用于表示注解应该被包含在生成的 Java 文档中(通过 Javadoc 工具)。这有助于为注解提供文档说明,让其他开发者了解注解的用途和用法。

    • 示例

@Documented
public @interface MyDocumentedAnnotation {
    String value();
}

  1. @Inherited

    • 作用 :用于表示一个注解类型是可以被继承的。当一个类使用了 @Inherited 修饰的注解,并且它的子类没有被注解时,子类会继承这个注解。

    • 示例

@Inherited
public @interface MyInheritedAnnotation {
    String value();
}
​
@MyInheritedAnnotation("父类注解")
class ParentClass {
}
​
class ChildClass extends ParentClass {
}

通过反射获取 ChildClass 的注解信息时,可以发现它继承了 ParentClass@MyInheritedAnnotation 注解。

二、Spring 注解

(一)组件扫描注解

  1. @Component

    • 作用 :用于将一个 Java 类标识为 Spring 组件,这样 Spring 容器会自动检测并管理这个类的实例。它是 Spring 的基本注解之一,常用于简单的组件类。

    • 示例

@Component
public class MyBean {
    public void doSomething() {
        System.out.println("MyBean doing something");
    }
}

在 Spring 配置中,通过组件扫描机制(如 @ComponentScan ),Spring 会发现 MyBean 类并将其作为 Bean 注入到 Spring 容器中。

  1. @Service

    • 作用 :用于标注服务层组件。它和 @Component 的功能相似,但语义更明确,表明这个类属于服务层,用于处理业务逻辑。

    • 示例

@Service
public class UserService {
    public void addUser() {
        System.out.println("添加用户");
    }
}

  1. @Repository

    • 作用 :用于标注数据访问层组件(DAO)。它主要用于对数据访问层的类进行标识,这样 Spring 可以对该类进行异常转换等操作,将低级的数据访问异常转换为 Spring 的数据访问异常体系。

    • 示例

@Repository
public class UserDAO {
    public void saveUser() {
        System.out.println("保存用户数据");
    }
}

  1. @Controller

    • 作用 :用于标注控制层组件。在 Spring MVC 中,它用于标注控制器类,处理客户端请求。

    • 示例

@Controller
public class MyController {
    @RequestMapping("/hello")
    public String sayHello() {
        System.out.println("Hello, Spring MVC");
        return "success";
    }
}

  1. @ComponentScan

    • 作用 :用于指定 Spring 容器扫描组件的包路径。这样,Spring 容器会自动检测在指定包及其子包下使用 @Component@Service@Repository@Controller 注解的类,并将其作为 Bean 加入到 Spring 容器中。

    • 示例

@Configuration
@ComponentScan(basePackages = "com.example")
public class AppConfig {
}

这表示 Spring 将扫描 com.example 包及其子包下的组件。

(二)依赖注入注解

  1. @Autowired

    • 作用 :用于自动装配 Bean。它可以根据类型来查找匹配的 Bean,然后将其注入到目标属性中。Spring 会自动完成依赖注入,减少了手动配置的复杂性。

    • 示例

@Component
public class MyClass {
    @Autowired
    private MyDependency myDependency;
​
    public void doSomething() {
        myDependency.doSomething();
    }
}

MyClass 中,myDependency 属性会自动注入类型为 MyDependency 的 Bean。

  1. @Qualifier

    • 作用 :用于指定注入特定的 Bean,当存在多个相同类型的 Bean 时,可以通过 @Qualifier 来明确指定注入哪一个 Bean。

    • 示例

@Component
public class MyBean1 {
    public void doSomething() {
        System.out.println("MyBean1 doing something");
    }
}
​
@Component
public class MyBean2 {
    public void doSomething() {
        System.out.println("MyBean2 doing something");
    }
}
​
@Component
public class MyClient {
    @Autowired
    @Qualifier("myBean1")
    private MyBean1 myBean;
}

在这个例子中,虽然 MyBean1MyBean2 都有 doSomething() 方法,但如果使用 @Qualifier("myBean1"),就会注入 MyBean1

  1. @Primary

    • 作用 :用于指定一个首选的 Bean。当存在多个相同类型的 Bean 时,Spring 会优先选择带有 @Primary 注解的 Bean 进行注入。

    • 示例

@Component
@Primary
public class MyBean1 {
    public void doSomething() {
        System.out.println("MyBean1 doing something");
    }
}
​
@Component
public class MyBean2 {
    public void doSomething() {
        System.out.println("MyBean2 doing something");
    }
}
​
@Component
public class MyClient {
    @Autowired
    private MyBean1 myBean;
}

由于 MyBean1 被标记为 @Primary,所以在自动注入时会优先选择它。

  1. @Value

    • 作用 :用于注入简单的值(如字符串、数字等),这些值可以从属性文件或其他配置中获取。

    • 示例

@Component
public class MyConfigBean {
    @Value("${my.config.value}")
    private String configValue;
​
    public void printConfig() {
        System.out.println("Config value: " + configValue);
    }
}

这里从配置文件中获取 my.config.value 的值并注入到 configValue 属性中。

(三)配置类注解

  1. @Configuration

    • 作用 :用于标记一个配置类,它告诉 Spring 这个类包含 Spring 容器的配置信息,类似于传统的 XML 配置文件。

    • 示例

@Configuration
@ComponentScan(basePackages = "com.example")
public class AppConfig {
}

  1. @Bean

    • 作用 :用于定义一个 Bean。在配置类中,通过在方法上添加 @Bean 注解,可以定义一个 Bean 并将其添加到 Spring 容器中。

    • 示例

@Configuration
public class AppConfig {
    @Bean
    public MyBean myBean() {
        return new MyBean();
    }
}

这样,myBean() 方法返回的实例会被作为 Bean 注入到 Spring 容器中。

  1. @Import

    • 作用 :用于导入其他配置类或组件。它可以将指定的类中的 Bean 定义导入到当前配置类中。

    • 示例

@Configuration
@Import(MyConfig.class)
public class MainConfig {
}

这会将 MyConfig 类中的 Bean 定义导入到 MainConfig 配置中。

(四)AOP(面向切面编程)注解

  1. @Aspect

    • 作用 :用于定义一个切面类。切面类包含多个切面相关的逻辑,如前置通知、后置通知等。

    • 示例

@Aspect
@Component
public class MyAspect {
    @Before("execution(* com.example.service.*.*(..))")
    public void beforeAdvice() {
        System.out.println("Before method execution");
    }
}

这个切面类定义了一个前置通知,在 com.example.service 包下的所有方法执行前会输出 “Before method execution”。

  1. @Before

    • 作用 :用于定义前置通知,表示在目标方法执行之前执行的逻辑。

    • 示例 :同上。

  2. @After

    • 作用 :用于定义后置通知,表示在目标方法执行之后执行的逻辑,无论目标方法是否正常结束。

    • 示例

@After("execution(* com.example.service.*.*(..))")
public void afterAdvice() {
    System.out.println("After method execution");
}

  1. @Around

    • 作用 :用于定义环绕通知,可以完全控制目标方法的执行流程。可以在方法执行前后添加自定义逻辑,并且可以选择是否执行目标方法。

    • 示例

@Around("execution(* com.example.service.*.*(..))")
public Object aroundAdvice(ProceedingJoinPoint joinPoint) throws Throwable {
    System.out.println("Around advice - before method execution");
    Object result = joinPoint.proceed(); // 执行目标方法
    System.out.println("Around advice - after method execution");
    return result;
}

  1. @Pointcut

    • 作用 :用于定义切点表达式,用于指定一组连接点(方法执行的点)作为切点,方便在多个通知中复用切点定义。

    • 示例

@Pointcut("execution(* com.example.service.*.*(..))")
public void serviceMethods() {}
​
@Before("serviceMethods()")
public void beforeAdvice() {
    System.out.println("Before service method execution");
}

(五)事务注解

  1. @Transactional

    • 作用 :用于声明事务边界,可以标注在类或方法上。它用于管理事务的开始、提交和回滚等操作,使得一组数据库操作要么全部成功,要么全部失败。

    • 示例

@Service
@Transactional
public class UserService {
    @Autowired
    private UserDAO userDAO;
​
    public void addUser(User user) {
        userDAO.saveUser(user);
        // 可能会抛出异常等,触发事务回滚
    }
}

在这个例子中,addUser() 方法被包含在事务中。如果在方法执行过程中出现异常,事务会回滚,确保数据的一致性。

三、Lombok 注解

Lombok 是一个 Java 库,通过注解的方式减少样板代码,提高代码的简洁性。

(一)常用注解

  1. @Data

    • 作用 :为类生成所有的标准 getter 和 setter 方法、equals()hashCode()toString() 方法,以及一个全参数的构造函数。它适用于简单的 Java Bean(POJO)类,可以大大减少代码量。

    • 示例

import lombok.Data;
​
@Data
public class User {
    private String name;
    private int age;
    private String email;
}

这个类会自动生成 getName()setName(String name) 等 getter 和 setter 方法,以及 equals()hashCode()toString() 方法,还有一个包含 nameageemail 参数的构造函数。

  1. @AllArgsConstructor

    • 作用 :为类生成一个包含所有字段的构造函数。这对于需要显式初始化所有字段的类很有用。

    • 示例

import lombok.AllArgsConstructor;
​
public class Product {
    private String name;
    private double price;
​
    @AllArgsConstructor
    public Product(String name, double price) {
        this.name = name;
        this.price = price;
    }
}

这个构造函数会自动为 nameprice 字段提供参数。

  1. @NoArgsConstructor

    • 作用 :为类生成一个无参构造函数。有些框架(如 Hibernate)可能需要无参构造函数来创建对象。

    • 示例

import lombok.NoArgsConstructor;
​
@NoArgsConstructor
public class Person {
    private String name;
    private int age;
}

  1. @ToString

    • 作用 :为类生成 toString() 方法,包含类的所有字段。可以自定义包含或排除某些字段。

    • 示例

import lombok.ToString;
​
@ToString
public class Book {
    private String title;
    private String author;
    private String isbn;
}

这会生成一个包含 titleauthorisbn 字段的 toString() 方法。

  1. @Getter 和 @Setter

    • 作用 :分别用于为类的字段生成 getter 方法和 setter 方法。可以单独控制每个字段的 getter 和 setter。

    • 示例

import lombok.Getter;
import lombok.Setter;
​
public class Car {
    @Getter @Setter
    private String brand;
​
    @Getter
    private int year;
}

在这个例子中,brand 字段既有 getter 又有 setter,而 year 字段只有 getter。

(二)其他注解

  1. @NonNull

    • 作用 :用于标记字段或方法参数,表示该字段或参数不能为 null。在构造函数或方法中,如果参数为 null,会抛出 NullPointerException

    • 示例

import lombok.NonNull;
​
public class Example {
    private String name;
​
    public Example(@NonNull String name) {
        this.name = name;
    }
}

注:如果传入的 namenull,构造函数会抛出异常。

Lombok 的注解可以帮助开发者减少大量的样板代码,提高开发效率,但需要注意的是,它在编译时会通过注解处理器将注解转换为实际的代码,所以在使用时需要确保 Lombok 插件正确配置在开发环境中(如在 IDE 中配置 Lombok 插件)。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值