Spring Boot中使用@Service注解时,底层具体执行逻辑是什么?
@Service本质是@Component的语义化派生注解,专门用来标记业务逻辑层的类,Spring处理它的核心流程和@Component一致,只是多了业务层的语义标识。当Spring扫描到@Service注解时,会执行以下关键操作:
1. 组件扫描与候选标记
Spring启动时,会根据@ComponentScan(或Spring Boot的@SpringBootApplication,它内置了ComponentScan)配置的包路径,递归扫描所有类。一旦发现类上标注了@Service,就会把这个类标记为候选组件,纳入Bean创建的流程。
2. Bean定义注册
Spring会为这个@Service类生成一个BeanDefinition对象,里面包含类的全限定名、默认作用域(singleton单例)、依赖信息、初始化/销毁回调等元数据,然后将这个BeanDefinition注册到BeanFactory中,相当于给Spring容器“登记”了这个Bean的信息。
3. Bean实例化与依赖注入
当Spring容器需要使用这个Bean时(比如其他类通过@Autowired注入,或者主动调用getBean()获取),会根据BeanDefinition创建类的实例。同时,Spring会自动解析这个Bean中所有的依赖注入注解(比如@Autowired、@Resource),把对应的协作Bean注入进来。
4. 生命周期回调执行
如果@Service类实现了InitializingBean/DisposableBean接口,或者使用了@PostConstruct/@PreDestroy注解,Spring会在对应的生命周期阶段执行这些回调方法:
- @PostConstruct:Bean实例化并完成依赖注入后立即执行
- @PreDestroy:容器关闭前执行
5. AOP代理生成(按需)
如果这个@Service类被Spring AOP的切面匹配(比如标注了@Transactional、@Cacheable等注解),Spring会动态生成一个代理对象,代替原Bean实例。后续对这个Bean的调用都会经过代理,从而实现事务管理、缓存等切面逻辑。
示例代码演示
1. 业务层Service类(@Service标记)
import org.springframework.stereotype.Service; import org.springframework.beans.factory.annotation.Autowired; import javax.annotation.PostConstruct; @Service public class UserService { // 注入DAO层依赖Bean @Autowired private UserDao userDao; // 核心业务方法 public String getUserDetail(Long userId) { return userDao.getUserNameById(userId); } // 初始化回调 @PostConstruct public void initService() { System.out.println("UserService 实例已完成初始化"); } }
2. DAO层类(@Repository标记,作为Service的依赖)
import org.springframework.stereotype.Repository; @Repository public class UserDao { public String getUserNameById(Long userId) { return "用户ID: " + userId + ",用户名: 李四"; } }
3. 配置类(开启组件扫描)
import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; @Configuration @ComponentScan("com.demo") // 扫描指定包下的所有组件 public class AppConfig { }
4. 测试类
import org.springframework.context.annotation.AnnotationConfigApplicationContext; public class AppTest { public static void main(String[] args) { AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class); // 获取UserService Bean,此时已完成实例化和依赖注入 UserService userService = context.getBean(UserService.class); System.out.println(userService.getUserDetail(1001L)); context.close(); } }
示例执行流程说明
- Spring启动后扫描
com.demo包,识别到UserService(@Service)和UserDao(@Repository),注册它们的Bean定义。 - 当获取
UserService实例时,Spring自动创建实例并注入UserDao的实例。 - 实例化完成后,执行
@PostConstruct标注的initService方法,打印初始化日志。 - 调用业务方法时,直接使用已注入的
UserDao完成数据查询。
内容的提问来源于stack exchange,提问作者Naomi

