Spring 核心注解深度分析

Spring框架的核心幼稚之一是通过注解驱动简化配置,实现组件解耦和功能扩展,注解本质就是元数据标记,Spring容器通过注解解析器识别这些标记,完成组件注册、依赖注入、事务管理等核心功能。

一、组件注册注解:将Bean纳入Spring容器管理

核心作用是告诉Spring容器,哪些类需要被实例化并纳入管理,替代传统XML中的<bean>标签

1.核心组件注解(Spring Context层)

|-----------------|----------------------------------|---------------------------------------------------------------------------------|
| 注解 | 使用场景 | 核心特点 |
| @Component | 通过组件注解,标记普通java类为Spring Bean | 没有特定的语义,适用于任何层 |
| @Service | 标记业务逻辑层(Service)租 | 语义化注解,底层与@Component完全一致 |
| @Repository | 标记数据访问层(DAO) 组件 | 除语义化外,额外支持 Spring 的「持久化异常转换」需配合 PersistenceExceptionTranslationPostProcessor) |
| @Controller | 标记Spring MVC 控制器(Controller) 组件 | 语义化注解,支持 Spring MVC 的请求映射(@RequestMapping 等),底层基于 @Component |
| @RestController | 标RESTful 风格控制器(Spring 4.0+) | 组合注解 = @Controller + @ResponseBody,默认所有方法返回 JSON/XML 而非视图 |

关键细节:

  • 这些注解默认通过「类路径扫描」生效,需在配置类中添加 @ComponentScan 指定扫描包(如 @ComponentScan("com.example"))。
  • Bean 的默认名称:类名首字母小写(如 UserServiceuserService),可通过注解 value 属性自定义(如 @Service("myUserService"))。

2.配置类相关注册注解

注解 作用场景 核心原理
@Configuration 标记类为配置类,替代传统 XML 配置文件 被标记的类会被 Spring 代理(CGLIB),确保 @Bean 方法单例(多次调用返回同一实例)
@Bean 用于配置类的方法上,手动注册 Bean(适用于第三方类,无法加 @Component 方法返回值作为 Bean 实例,默认名称为方法名,可通过 @Bean("beanName") 自定义
@Import 快速导入 Bean 或配置类(无需扫描) 支持 3 种类型:普通类(直接注册为 Bean)、ImportSelector 实现类(动态导入)、ImportBeanDefinitionRegistrar 实现类(手动注册 BeanDefinition)
@Conditional 条件化注册 Bean(Spring 4.0+) 配合 Condition 接口,满足条件时才注册 Bean(如 @Conditional(OnClassCondition.class) 检查类是否存在)
示例:@Bean 注册第三方组件
复制代码
@Configuration
public class ThirdPartyConfig {
    // 注册 RedisTemplate(第三方类,无法加 @Component)
    @Bean("myRedisTemplate")
    public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory) {
        RedisTemplate<String, Object> template = new RedisTemplate<>();
        template.setConnectionFactory(factory);
        return template;
    }
}

二、依赖注入注解:解决 Bean 之间的依赖关系

核心作用是让 Spring 容器自动将依赖的 Bean 注入到目标组件中,替代传统 XML 中的 <property> 或构造器注入。

1. 核心注入注解

注解 注入方式 适用场景与注意事项
@Autowired Spring 自带注解,按类型(byType) 注入 1. 优先匹配类型一致的 Bean,若存在多个同类型 Bean,需配合 @Qualifier 指定名称;2. 默认要求依赖必须存在(可通过 required = false 允许空值);3. 支持构造器、字段、setter 方法注入
@Qualifier 配合 @Autowired,按名称(byName) 注入 解决同类型多 Bean 冲突(如 @Autowired @Qualifier("userServiceV2")
@Resource JDK 原生注解(JSR-250),按名称优先注入 1. 先按名称匹配,名称不存在则按类型匹配;2. 支持字段、setter 方法注入,不支持构造器注入;3. 无需配合其他注解,直接指定名称(@Resource(name = "userDao")
@Value 注入基本类型 / 字符串值,支持 SpEL 表达式 1. 注入配置文件值(如 @Value("${app.name}"),需配合 @PropertySource 加载配置文件);2. 注入常量(如 @Value("10"))或 SpEL 表达式(如 @Value("#{T(java.lang.Math).random()}
注入方式优先级(Spring 推荐):
  1. 构造器注入 :强制依赖初始化,避免空指针,且组件不可变(final 字段),Spring 4.3+ 支持无 @Autowired 的构造器注入(仅一个构造器时);
  2. setter 注入:适用于可选依赖;
  3. 字段注入:代码简洁,但可读性差,且无法注入 final 字段,不推荐大量使用。
示例:构造器注入(推荐)
复制代码
@Service
public class UserService {
    private final UserDao userDao;
    private final OrderService orderService;

    // Spring 4.3+ 无需 @Autowired(仅一个构造器)
    public UserService(UserDao userDao, @Qualifier("orderServiceV2") OrderService orderService) {
        this.userDao = userDao;
        this.orderService = orderService;
    }
}

2. 配置文件加载注解

注解 作用场景 示例
@PropertySource 加载外部 properties 配置文件(Spring 3.1+) @PropertySource("classpath:application.properties")(加载类路径下的配置文件)
@PropertySources 加载多个 properties 文件(Spring 4.0+) @PropertySources({@PropertySource("a.properties"), @PropertySource("b.properties")})

三、Bean 生命周期注解:控制 Bean 的创建与销毁

Spring Bean 的生命周期:实例化 → 属性注入 → 初始化 → 销毁,注解用于干预初始化和销毁阶段。

注解 作用时机 核心特点
@PostConstruct JDK 原生注解(JSR-250),Bean 初始化完成后执行(属性注入后) 1. 无参数、无返回值的非静态方法;2. 执行时机:BeanPostProcessor.postProcessAfterInitialization 之前
@PreDestroy JDK 原生注解(JSR-250),Bean 销毁前执行(容器关闭时) 1. 无参数、无返回值的非静态方法;2. 仅适用于单例 Bean(原型 Bean 容器不管理销毁)
@Bean(initMethod = "init", destroyMethod = "destroy") 配置类中 @Bean 方法指定初始化 / 销毁方法 适用于第三方类(无法加 @PostConstruct),如 @Bean(initMethod = "start", destroyMethod = "stop")
执行顺序:

构造器 → @Autowired(属性注入) → @PostConstruct(初始化) → 业务逻辑 → @PreDestroy(销毁)

四、AOP 与事务注解:面向切面编程与事务管理

1. AOP 核心注解(Spring AOP)

AOP 用于分离核心业务与横切逻辑(如日志、权限、异常处理),Spring AOP 基于动态代理实现。

注解 作用场景 核心说明
@Aspect 标记类为切面类(包含通知和切入点) 需配合 @EnableAspectJAutoProxy(Spring 4.0+)开启 AOP 自动代理
@Pointcut 定义切入点表达式(指定哪些方法需要被增强) 常用表达式:- execution(方法匹配):execution(* com.example.service.*.*(..))(匹配 service 层所有方法);- @annotation(注解匹配):@annotation(com.example.annotation.Log)(匹配加了 @Log 注解的方法)
@Before 前置通知:目标方法执行前执行
@AfterReturning 返回通知:目标方法正常返回后执行(异常时不执行) 可通过 returning 参数获取返回值:@AfterReturning(pointcut = "pc()", returning = "result")
@AfterThrowing 异常通知:目标方法抛出异常后执行 可通过 throwing 参数获取异常对象:@AfterThrowing(pointcut = "pc()", throwing = "e")
@After 最终通知:目标方法执行后执行(无论正常 / 异常,类似 finally)
@Around 环绕通知:包裹目标方法,可控制目标方法的执行(最强大) 需通过 ProceedingJoinPoint 调用 proceed() 执行目标方法,可修改参数、返回值或异常
示例:日志切面
复制代码
@Aspect
@Component
public class LogAspect {
    // 切入点:匹配 service 层所有方法
    @Pointcut("execution(* com.example.service.*.*(..))")
    public void servicePointcut() {}

    // 环绕通知:记录方法执行时间
    @Around("servicePointcut()")
    public Object logExecutionTime(ProceedingJoinPoint joinPoint) throws Throwable {
        long start = System.currentTimeMillis();
        Object result = joinPoint.proceed(); // 执行目标方法
        long time = System.currentTimeMillis() - start;
        System.out.println(joinPoint.getSignature() + " 执行时间:" + time + "ms");
        return result;
    }
}

// 启动类开启 AOP
@SpringBootApplication
@EnableAspectJAutoProxy
public class Application {
    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
}

2. 事务管理注解(Spring Transaction)

基于 AOP 实现声明式事务,替代传统 XML 中的 <tx:advice> 配置。

注解 作用场景 核心属性与注意事项
@Transactional 标记方法 / 类需要事务管理(声明式事务) 1. 作用范围 :类上(所有方法生效)、方法上(覆盖类上配置);2. 核心属性:- propagation:事务传播行为(如 REQUIRED 【默认】、REQUIRES_NEW);- isolation:事务隔离级别(如 READ_COMMITTED 【默认】);- rollbackFor:指定触发回滚的异常(如 rollbackFor = Exception.class,默认仅运行时异常回滚);- readOnly:是否只读事务(查询方法设为 true,优化性能);3. 需配合 @EnableTransactionManagement 开启事务管理(Spring Boot 自动开启)
关键注意事项:
  • @Transactional 仅对public 方法生效(Spring AOP 动态代理限制);
  • 内部方法调用(如 A.methodA() 调用本类 @Transactional methodB())不会触发事务(代理对象未介入),需通过 AopContext.currentProxy() 获取代理对象调用。

五、注解使用核心原则

  1. 语义化优先 :如 Service 层用 @Service,DAO 层用 @Repository,而非全用 @Component,提升代码可读性;
  2. 依赖注入推荐构造器注入:避免空指针,支持不可变对象(final 字段);
  3. 事务注解注意作用范围:仅 public 方法生效,避免内部调用;
  4. 配置类避免组件扫描冲突@Configuration 配合 @Bean 注册第三方组件,@ComponentScan 扫描自定义组件;
  5. AOP 切面类需加 @Component :确保切面类被 Spring 容器管理,否则 @Aspect 不生效。
相关推荐
武子康1 小时前
大数据-160 Apache Kylin Cube 实战:从建模到构建与查询(含踩坑与优化)
大数据·后端·apache kylin
9***Y481 小时前
Java开发工具IntelliJ IDEA技巧
java·开发语言·intellij-idea
Java爱好狂.1 小时前
2025全年Java面试真题总结!
java·jvm·高并发·多线程·java面试·后端开发·java八股文
Charles_go2 小时前
C#中级39、什么是依赖注入设计模式
java·设计模式·c#
ComplexPy2 小时前
ZKMall-B2B2C Redission延时队列
java·redis
q***96582 小时前
深入解析Spring Boot中的@ConfigurationProperties注解
java·spring boot·后端
java1234_小锋2 小时前
讲讲Mybatis的一级、二级缓存?
java·开发语言·mybatis
e***87702 小时前
记录 idea 启动 tomcat 控制台输出乱码问题解决
java·tomcat·intellij-idea
发现你走远了2 小时前
2025 idea 指定配置环境运行springboot 设置active和env启动端口,多端口启动 (保姆级图文)
java·spring boot·intellij-idea