介绍
我们知道Spring生态圈或者说全家桶非常的好用,其中注解贯彻其中,下面我来简单归纳一下Spring的常用注解。
Bean管理相关
@Component
万能通用组件,当你给一个普通的 Java 类加上@Component注解后,Spring 在启动时会通过组件扫描机制(@ComponentScan)自动发现它,利用反射机制在内存中把它new出来,并作为一个 Bean 存放到 IoC 容器中。以下是其三个特化的形式(理论上可以互相替换,但不建议,要保持新人友好原则嘛)。
@Service
@Service:用在业务逻辑层(Service 层)。
@Repository
@Repository:用在数据访问层(DAO 层),自带数据库异常转换功能。
@Controller
@Controller:用在 Web 控制层,处理 HTTP 请求。
注入依赖方面
@Autowired
@Autowired:Spring 提供的自动装配注解,默认按类型(byType)注入。如果同类型有多个 Bean,会报错。
底层注入逻辑:@Autowired 的自动装配并非魔法,而是基于 Spring 的依赖注入机制和 Java 反射技术实现的。其核心流程主要依赖一个关键的后置处理器:AutowiredAnnotationBeanPostProcessor。
具体过程如下:
1.扫描与元数据封装:当 Spring 容器启动并创建 Bean 时,AutowiredAnnotationBeanPostProcessor 会扫描当前类中所有带有 @Autowired 注解的字段、方法或构造函数。它会将这些注入点的信息(如类型、名称等)封装成 InjectionMetadata 对象并缓存起来。
2.属性填充(注入阶段):在 Bean 实例化之后、初始化之前,Spring 会调用该后置处理器的 postProcessProperties 方法。它会遍历之前缓存的 InjectionMetadata,通过反射机制在 Spring 的 IoC 容器中查找匹配的 Bean,然后将其赋值给目标字段或作为参数传入方法中。
为何同类型多个注入会报错:
@Autowired 默认的装配策略是 按类型自动装配(byType)。当容器中存在多个相同类型的 Bean 时,就会触发以下逻辑:
1.按类型查找:Spring 首先根据字段或参数的类型去容器中查找。如果只找到一个,直接注入;如果找不到,且 required=true(默认值),则抛出 NoSuchBeanDefinitionException 异常。
2.按名称消歧(byName):如果找到了多个同类型的 Bean,Spring 会尝试将注入点的变量名作为 Bean 的名称去进一步匹配。例如,如果你写的是 @Autowired private UserService userService1;,Spring 会尝试在多个同类型 Bean 中寻找名为 userService1 的那个。
3.抛出异常:如果变量名也无法匹配到唯一的 Bean,Spring 就会陷入“不知道该注入哪一个”的困境,从而抛出 NoUniqueBeanDefinitionException 异常。
4.如何解决多个同类型 Bean 的冲突?
下面介绍的@Qualifier可以用来解决这个问题
@Qualifier
@Qualifier:配合@Autowired使用,当有多个同类型 Bean 时,指定按名称(byName)注入具体的 Bean。
@Resource
@Resource:Java 原生标准注解(非 Spring 独有),默认按名称(byName)注入,找不到名称再按类型注入,不需要配合 @Qualifier。
一句话总结@Autowired和@Resource的用法区别
@Autowired 是 Spring 的亲儿子,按类型找,找不到再按名字找;@Resource 是 Java 的干儿子,按名字找,找不到再按类型找。在实际开发中,优先使用 @Autowired 进行构造函数注入,需要按名称注入时再用 @Resource。
配置相关注解
@Configuration
@Configuration:声明一个类为配置类,用来替代传统的 XML 配置文件,里面通常配合 @Bean 使用。
@PropertySource注解会告诉Spring从指定的类路径下加载jdbc.properties这个文件
@Bean
@Bean注解的作用是告诉Spring,这个方法的返回值是一个需要交给Spring容器管理的Bean对象,Spring容器会自动调用这个方法,把方法返回的对象创建出来,存入IOC容器中。
就比如以下两个方法是第三方的不是我写的但是我可以用@Bean把他们的返回值注入到IOC容器中让它帮我创建。
@Value
@Value:用于注入配置文件中的基本数据类型或字符串属性值(如 @Value("${app.name}"))。
如果数据量小的情况不用@ConfigurationProperties(适合批量注入的情况)的情况下我们用@Value和@Configuration来配合注入文件。
@PropertySource
将配置文件(如 application.yml)中的属性批量绑定到一个 Java 对象上,比 @Value 更适合管理大量配置。
@PropertySource和@Value配合使用,@PropertySource 注解本身是直接标注在类上生效的,它的作用就是加载指定的外部配置文件(这里就是 jdbc.properties),让配置文件中的属性能够被 Spring 容器识别,后续才能通过 @Value 注入属性值。@PropertySource 负责做第一步:指定要加载哪个外部properties配置文件,@Value 负责做第二步:把配置文件中对应key的属性值注入到成员变量中。
@PropertySource 配合 @Value 确实比硬编码写数据库连接信息要方便很多,而如果要比一个个写 @Value 更便捷的方式,可以用 Spring Boot 提供的 @ConfigurationProperties 批量注入属性,这里讲的是基础注解,不多赘述。