前言:我们前面学习了Sping家族的相关框架,用的最多的就是注解了。里面有非常多的注解,我们常常会傻傻搞不清,那么我通过这篇文章让你拿下Spring家族的所有重要注解,并对一些注解进行源码解读。
Spring & Spring Boot 核心注解速查表
| 注解 | 主要用途 | 所属框架 |
|---|---|---|
@Component |
通用的Spring托管Bean注解 | Spring |
@Service |
标识业务逻辑层(Service层)的组件 | Spring |
@Repository |
标识数据访问层(DAO层)的组件,自带异常转换 | Spring |
@Controller |
标识展现层(Web层)的组件 | Spring MVC |
@Configuration |
标识一个类为Java配置类,可包含@Bean方法 |
Spring |
@Bean |
标注在方法上,将方法返回值注册为一个Bean | Spring |
@ComponentScan |
配置组件扫描的路径 | Spring |
@Autowired |
按类型自动装配依赖 | Spring |
@Qualifier |
与@Autowired联用,按名称指定具体注入的Bean |
Spring |
@Value |
注入外部配置文件(如application.properties)的属性值 |
Spring |
@Scope |
定义Bean的作用域(如singleton、prototype) | Spring |
@Primary |
当有多个相同类型的Bean时,优先注入被该注解标记的Bean | Spring |
@Import |
导入一个或多个配置类 | Spring |
@PropertySource |
加载指定的properties配置文件 | Spring |
@ConfigurationProperties |
将配置文件中的属性绑定到一个POJO类上 | Spring Boot |
Spring MVC / Web 层开发
| 注解 | 主要用途 | 所属框架 |
|---|---|---|
@RestController |
@Controller + @ResponseBody的组合,用于RESTful API |
Spring MVC |
@RequestMapping |
映射URL路径到控制器类或方法上 | Spring MVC |
@GetMapping |
@RequestMapping(method = RequestMethod.GET)的简写 |
Spring MVC |
@PostMapping |
@RequestMapping(method = RequestMethod.POST)的简写 |
Spring MVC |
@PutMapping |
@RequestMapping(method = RequestMethod.PUT)的简写 |
Spring MVC |
@DeleteMapping |
@RequestMapping(method = RequestMethod.DELETE)的简写 |
Spring MVC |
@PathVariable |
获取URL模板中的变量值 | Spring MVC |
@RequestParam |
获取请求参数(Query String或Form数据) | Spring MVC |
@RequestBody |
将HTTP请求体(JSON/XML)绑定到方法参数上 | Spring MVC |
@ResponseBody |
将方法返回值直接写入HTTP响应体(如返回JSON) | Spring MVC |
@ControllerAdvice |
全局处理控制器,用于异常处理、数据绑定等 | Spring MVC |
@ExceptionHandler |
用于处理特定异常的注解 | Spring MVC |
数据访问(JPA / JDBC)
| 注解 | 主要用途 | 所属框架 |
|---|---|---|
@Transactional |
声明方法或类的事务边界 | Spring |
@Entity |
标识一个JPA实体类 | JPA |
@Table |
指定实体类映射的数据库表名 | JPA |
@Id |
标识实体类的主键字段 | JPA |
@GeneratedValue |
指定主键的生成策略 | JPA |
@Column |
指定字段映射的数据库列名及属性 | JPA |
高级特性与AOP
| 注解 | 主要用途 | 所属框架 |
|---|---|---|
@Aspect |
标识一个类为切面类 | Spring AOP |
@Before |
定义前置通知 | Spring AOP |
@After |
定义后置通知 | Spring AOP |
@Around |
定义环绕通知 | Spring AOP |
@Pointcut |
定义切入点表达式 | Spring AOP |
@EnableAspectJAutoProxy |
开启对AspectJ注解的支持 | Spring AOP |
@Async |
声明一个方法为异步执行 | Spring |
@Scheduled |
声明一个方法为定时任务 | Spring |
@Conditional及其派生注解 |
根据特定条件来决定是否创建Bean | Spring Boot |
@SpringBootApplication |
Spring Boot应用启动类核心注解(组合了@Configuration、@EnableAutoConfiguration、@ComponentScan) |
Spring Boot |
Spring Cloud 微服务
| 注解 | 主要用途 | 所属框架 |
|---|---|---|
@EnableEurekaServer |
启动一个Eureka服务注册中心 | Spring Cloud Netflix |
@EnableDiscoveryClient |
让服务实例能被服务发现组件(如Eureka、Consul)发现 | Spring Cloud Commons |
@LoadBalanced |
为RestTemplate赋予客户端负载均衡能力(如Ribbon) |
Spring Cloud Commons |
@FeignClient |
声明一个声明式的HTTP客户端,用于调用其他微服务 | Spring Cloud OpenFeign |
@EnableCircuitBreaker / @EnableHystrix |
开启断路器功能 | Spring Cloud Netflix |
@HystrixCommand |
配置Hystrix命令的熔断和降级逻辑 | Spring Cloud Netflix |
@EnableConfigServer |
启动Spring Cloud配置中心服务端 | Spring Cloud Config |
@RefreshScope |
使配置类或Bean支持动态刷新配置 | Spring Cloud Commons |
@EnableZuulProxy |
启用Zuul网关代理功能 | Spring Cloud Netflix |
@EnableResourceServer |
启用OAuth2资源服务器功能 | Spring Cloud Security |
@PreAuthorize |
方法级别的权限控制,基于表达式 | Spring Security |
注解源码分析
@Component
++@Component是所有被Spring管理的Bean的源头,像@Service、@Repository等注解都派生自它++
源码:
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Indexed
public @interface Component {
@AliasFor("value")
String name() default "";
@AliasFor("name")
String value() default "";
}
设计分析:
-
元注解 :
@Target(ElementType.TYPE)表示只能用于类(或接口);@Retention(RetentionPolicy.RUNTIME)确保注解在运行时可以通过反射读取,这是Spring容器工作的基础。 -
@Indexed:从Spring 5引入,用于构建候选组件索引,避免类路径扫描,从而提升大型项目的启动速度。 -
@AliasFor的双向别名 :value()和name()互为别名,让开发者可以自由选择@Component("myBean")或@Component(name="myBean"),API设计上更人性化。
@Autowired --- 依赖注入的核心
++@Autowired是依赖注入的入口。它本身只是一个标记,真正的工作是由AutowiredAnnotationBeanPostProcessor完成的。++
@Target({ElementType.CONSTRUCTOR, ElementType.METHOD,
ElementType.PARAMETER, ElementType.FIELD, ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Autowired {
boolean required() default true;
}
工作流程剖析:
-
注册处理器 :Spring容器启动
refresh()时,会注册AutowiredAnnotationBeanPostProcessor。 -
预解析元数据 :在Bean实例化阶段,该后置处理器调用
postProcessMergedBeanDefinition(),扫描Bean中的@Autowired(字段/方法),将待注入的信息封装成InjectionMetadata对象。 -
执行属性填充 :在
populateBean()阶段,再次调用后置处理器的postProcessPropertyValues(),遍历InjectionMetadata。根据类型或名称(配合@Qualifier)从容器中查找依赖,通过反射暴力赋值
@Transactional --- 声明式事务
@Transactional通过AOP实现,将复杂的事务管理逻辑与业务代码解耦
5.
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@Documented
public @interface Transactional {
@AliasFor("transactionManager")
String value() default "";
@AliasFor("value")
String transactionManager() default "";
Propagation propagation() default Propagation.REQUIRED;
Isolation isolation() default Isolation.DEFAULT;
boolean readOnly() default false;
// ... 其他属性
-
代理模式:Spring会为目标Bean创建代理对象(JDK动态代理或CGLIB)。调用
@Transactional方法时,实际调用的是代理对象。 -
拦截器链:
TransactionInterceptor(事务拦截器)在代理中发挥作用,执行环绕通知。 -
事务决断
@SpringBootApplication --- 一键启动
++@SpringBootApplication是一个复合注解,它将三个核心功能打包在一起,极大简化了配置++
-
@SpringBootConfiguration:本质是@Configuration,标记当前类是配置类。 -
@ComponentScan:启动自动扫描,默认扫描主类所在包及其子包。 -
@EnableAutoConfiguration:核心中的核心 。它通过@Import(AutoConfigurationImportSelector.class)导入一大批自动配置类。AutoConfigurationImportSelector会读取META-INF/spring.factories文件,根据当前类路径下的依赖(如有无DataSource类)有选择地启用配置。 -
proxyBeanMethods属性 :默认为true,即Full模式 。此时Spring会通过CGLIB创建配置类的代理,确保@Bean方法间相互调用时是单例的,而非重新创建对象。
@Configuration
++@Configuration用于标记一个类为Spring的配置类。Spring IoC容器在启动时,会读取这个类中定义的方法,并根据这些方法来创建和组装Bean。++
-
@Component的派生 :@Configuration上标有@Component,这意味着所有带@Configuration的类本身也会被Spring容器当作一个Bean来管理。 -
proxyBeanMethods:这是理解@Configuration最核心 的开关,默认值为true。
Full 模式 (proxyBeanMethods = true,默认)
-
特点:Spring会通过CGLIB动态代理 创建一个配置类的代理对象。
-
行为:当你调用配置类中被@Bean标记的方法时,不会真的执行该方法 ,而是直接从Spring容器中(IoC单例池)获取已经创建好的单例Bean 。
-
意义:保证了Bean的单例性。无论你在代码中显式调用多少次myService(),得到的都是同一个实例。
Lite 模式 (proxyBeanMethods = false)
-
特点:这是一个普通的Spring Bean ,不会经过CGLIB增强,就是一个普通的
@Component类。 -
行为:当你调用
@Bean方法时,方法体真的会被执行,每次都返回一个新的对象。 -
应用场景:适用于那些不需要在配置类内部通过方法调用相互引用的场景,例如简单的工具类配置,或者导入其他配置,可以减少启动开销。
-
Spring启动,扫描到
@Configuration,创建AppConfig的代理对象。 -
调用代理对象的
myService()方法 -> 代理逻辑拦截 -> 检查容器中是否有MyService类型的Bean? -
如果没有,执行真正的
new MyService(),放入容器,返回实例。 -
调用代理对象的
myController()方法,执行方法体,其中又调用了myService()。 -
再次调用
myService()方法 -> 代理逻辑再次拦截 -> 此时容器中已经有MyService实例了,直接返回该实例,而不会再执行new MyService()。 -
MyController拿到了与之前完全相同的MyService实例。
对比
| 维度 | @Configuration |
@Component |
|---|---|---|
| 角色 | 专门用于定义Bean的配置源 | 通用的Bean,用于业务逻辑 |
| 代理机制 | 默认有CGLIB代理,保证单例 | 无代理,就是个普通Bean |
| 方法调用 | @Bean方法间相互调用返回的是容器中的单例对象 |
@Bean方法间调用就是普通的Java方法调用,每次返回新对象 |
| 目的 | 替代XML,集中管理Bean定义 | 让Spring管理业务类实例 |
总结:
-
注解即标记:注解本身仅包含属性和元数据,不包含业务逻辑。
-
处理器负责干活 :真正的功能由各种
*Processor(如AutowiredAnnotationBeanPostProcessor)、*Interceptor(如TransactionInterceptor)或*ImportSelector实现。 -
利用反射和代理 :核心实现手段是反射 (如
@Autowired赋值)和动态代理 (如@Transactional、@Configuration)。
如果对你有帮助,请一键三连,蟹蟹了