一、Java 自带注解
(一)基本注解
-
@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()
方法。
-
@Deprecated
-
作用 :用于标记一个程序元素(如类、方法、字段等)已经过时。当使用被标记为过时的元素时,编译器会发出警告。这通常是因为有更好的替代方案,或者该元素可能在未来的版本中被删除。
-
示例
-
@Deprecated public class OldClass { public void oldMethod() { System.out.println("旧方法"); } }
当其他代码使用 OldClass
或 oldMethod()
时,编译器会提示该类和方法已经过时。
-
@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>
),但这里使用了原始类型。
(二)元注解
元注解是用来定义其他注解的注解,它们主要用于框架或工具的开发。
-
@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
只能应用在字段上。
-
@Retention
-
作用 :用于指定注解的生命周期。
-
常见参数
-
RetentionPolicy.SOURCE
:注解只保留在源代码中,编译时就会被忽略,不会写入到字节码文件中。 -
RetentionPolicy.CLASS
:注解会被写入到字节码文件中,但在运行时会被虚拟机忽略,不能通过反射获取。 -
RetentionPolicy.RUNTIME
:注解会被写入字节码文件中,并且可以在运行时通过反射获取。
-
-
示例
-
@Retention(RetentionPolicy.RUNTIME) public @interface MyRuntimeAnnotation { String value(); }
这个自定义注解 @MyRuntimeAnnotation
在运行时可以通过反射获取。
-
@Documented
-
作用 :用于表示注解应该被包含在生成的 Java 文档中(通过 Javadoc 工具)。这有助于为注解提供文档说明,让其他开发者了解注解的用途和用法。
-
示例
-
@Documented public @interface MyDocumentedAnnotation { String value(); }
-
@Inherited
-
作用 :用于表示一个注解类型是可以被继承的。当一个类使用了
@Inherited
修饰的注解,并且它的子类没有被注解时,子类会继承这个注解。 -
示例
-
@Inherited public @interface MyInheritedAnnotation { String value(); } @MyInheritedAnnotation("父类注解") class ParentClass { } class ChildClass extends ParentClass { }
通过反射获取 ChildClass
的注解信息时,可以发现它继承了 ParentClass
的 @MyInheritedAnnotation
注解。
二、Spring 注解
(一)组件扫描注解
-
@Component
-
作用 :用于将一个 Java 类标识为 Spring 组件,这样 Spring 容器会自动检测并管理这个类的实例。它是 Spring 的基本注解之一,常用于简单的组件类。
-
示例
-
@Component public class MyBean { public void doSomething() { System.out.println("MyBean doing something"); } }
在 Spring 配置中,通过组件扫描机制(如 @ComponentScan
),Spring 会发现 MyBean
类并将其作为 Bean 注入到 Spring 容器中。
-
@Service
-
作用 :用于标注服务层组件。它和
@Component
的功能相似,但语义更明确,表明这个类属于服务层,用于处理业务逻辑。 -
示例
-
@Service public class UserService { public void addUser() { System.out.println("添加用户"); } }
-
@Repository
-
作用 :用于标注数据访问层组件(DAO)。它主要用于对数据访问层的类进行标识,这样 Spring 可以对该类进行异常转换等操作,将低级的数据访问异常转换为 Spring 的数据访问异常体系。
-
示例
-
@Repository public class UserDAO { public void saveUser() { System.out.println("保存用户数据"); } }
-
@Controller
-
作用 :用于标注控制层组件。在 Spring MVC 中,它用于标注控制器类,处理客户端请求。
-
示例
-
@Controller public class MyController { @RequestMapping("/hello") public String sayHello() { System.out.println("Hello, Spring MVC"); return "success"; } }
-
@ComponentScan
-
作用 :用于指定 Spring 容器扫描组件的包路径。这样,Spring 容器会自动检测在指定包及其子包下使用
@Component
、@Service
、@Repository
和@Controller
注解的类,并将其作为 Bean 加入到 Spring 容器中。 -
示例
-
@Configuration @ComponentScan(basePackages = "com.example") public class AppConfig { }
这表示 Spring 将扫描 com.example
包及其子包下的组件。
(二)依赖注入注解
-
@Autowired
-
作用 :用于自动装配 Bean。它可以根据类型来查找匹配的 Bean,然后将其注入到目标属性中。Spring 会自动完成依赖注入,减少了手动配置的复杂性。
-
示例
-
@Component public class MyClass { @Autowired private MyDependency myDependency; public void doSomething() { myDependency.doSomething(); } }
在 MyClass
中,myDependency
属性会自动注入类型为 MyDependency
的 Bean。
-
@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; }
在这个例子中,虽然 MyBean1
和 MyBean2
都有 doSomething()
方法,但如果使用 @Qualifier("myBean1")
,就会注入 MyBean1
。
-
@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
,所以在自动注入时会优先选择它。
-
@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
属性中。
(三)配置类注解
-
@Configuration
-
作用 :用于标记一个配置类,它告诉 Spring 这个类包含 Spring 容器的配置信息,类似于传统的 XML 配置文件。
-
示例
-
@Configuration @ComponentScan(basePackages = "com.example") public class AppConfig { }
-
@Bean
-
作用 :用于定义一个 Bean。在配置类中,通过在方法上添加
@Bean
注解,可以定义一个 Bean 并将其添加到 Spring 容器中。 -
示例
-
@Configuration public class AppConfig { @Bean public MyBean myBean() { return new MyBean(); } }
这样,myBean()
方法返回的实例会被作为 Bean 注入到 Spring 容器中。
-
@Import
-
作用 :用于导入其他配置类或组件。它可以将指定的类中的 Bean 定义导入到当前配置类中。
-
示例
-
@Configuration @Import(MyConfig.class) public class MainConfig { }
这会将 MyConfig
类中的 Bean 定义导入到 MainConfig
配置中。
(四)AOP(面向切面编程)注解
-
@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”。
-
@Before
-
作用 :用于定义前置通知,表示在目标方法执行之前执行的逻辑。
-
示例 :同上。
-
-
@After
-
作用 :用于定义后置通知,表示在目标方法执行之后执行的逻辑,无论目标方法是否正常结束。
-
示例
-
@After("execution(* com.example.service.*.*(..))") public void afterAdvice() { System.out.println("After method execution"); }
-
@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; }
-
@Pointcut
-
作用 :用于定义切点表达式,用于指定一组连接点(方法执行的点)作为切点,方便在多个通知中复用切点定义。
-
示例
-
@Pointcut("execution(* com.example.service.*.*(..))") public void serviceMethods() {} @Before("serviceMethods()") public void beforeAdvice() { System.out.println("Before service method execution"); }
(五)事务注解
-
@Transactional
-
作用 :用于声明事务边界,可以标注在类或方法上。它用于管理事务的开始、提交和回滚等操作,使得一组数据库操作要么全部成功,要么全部失败。
-
示例
-
@Service @Transactional public class UserService { @Autowired private UserDAO userDAO; public void addUser(User user) { userDAO.saveUser(user); // 可能会抛出异常等,触发事务回滚 } }
在这个例子中,addUser()
方法被包含在事务中。如果在方法执行过程中出现异常,事务会回滚,确保数据的一致性。
三、Lombok 注解
Lombok 是一个 Java 库,通过注解的方式减少样板代码,提高代码的简洁性。
(一)常用注解
-
@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()
方法,还有一个包含 name
、age
和 email
参数的构造函数。
-
@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; } }
这个构造函数会自动为 name
和 price
字段提供参数。
-
@NoArgsConstructor
-
作用 :为类生成一个无参构造函数。有些框架(如 Hibernate)可能需要无参构造函数来创建对象。
-
示例
-
import lombok.NoArgsConstructor; @NoArgsConstructor public class Person { private String name; private int age; }
-
@ToString
-
作用 :为类生成
toString()
方法,包含类的所有字段。可以自定义包含或排除某些字段。 -
示例
-
import lombok.ToString; @ToString public class Book { private String title; private String author; private String isbn; }
这会生成一个包含 title
、author
和 isbn
字段的 toString()
方法。
-
@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。
(二)其他注解
-
@NonNull
-
作用 :用于标记字段或方法参数,表示该字段或参数不能为
null
。在构造函数或方法中,如果参数为null
,会抛出NullPointerException
。 -
示例
-
import lombok.NonNull; public class Example { private String name; public Example(@NonNull String name) { this.name = name; } }
注:如果传入的 name
为 null
,构造函数会抛出异常。
Lombok 的注解可以帮助开发者减少大量的样板代码,提高开发效率,但需要注意的是,它在编译时会通过注解处理器将注解转换为实际的代码,所以在使用时需要确保 Lombok 插件正确配置在开发环境中(如在 IDE 中配置 Lombok 插件)。