☰
Spring 全注解开发详解
2026/10/3 20:36:29 网站建设 项目流程

Spring 全注解开发详解

一、什么是全注解开发

全注解开发是指完全摆脱 XML 配置文件,用 Java 类 + 注解来构建 Spring 应用。配置类替代了applicationContext.xml,注解替代了<bean>、<property>、<constructor-arg>等标签。

传统 XML 方式需要维护多个配置文件,配置和代码分离,修改配置要改 XML。全注解方式把配置和代码放在一起,类上标注解就能被 Spring 管理,方法参数自动注入依赖,配置类替代 XML 文件。

Spring Boot 就是全注解开发的极致体现,但理解全注解开发,需要先掌握 Spring Framework 层面的注解体系。

二、从 XML 到注解的演进

XML 时代:

<beanid="userDao"class="com.example.UserDao"/><beanid="userService"class="com.example.UserService"><propertyname="userDao"ref="userDao"/></bean>

注解时代:

@RepositorypublicclassUserDao{}@ServicepublicclassUserService{@AutowiredprivateUserDaouserDao;}

配置从 XML 转移到了 Java 类上。类的职责和依赖关系一目了然,不需要在 XML 和 Java 之间来回切换。

三、核心注解体系

1. 声明 Bean

注解语义适用层
@Component通用组件任意
@Service业务层Service
@Repository数据访问层Dao
@Controller控制层Controller
@RestControllerREST 控制器Controller
@Configuration配置类配置
@ServicepublicclassUserService{}@RepositorypublicclassUserDao{}

Bean 名称默认是类名首字母小写,可以显式指定:

@Service("userService")publicclassUserService{}

2. 配置类与 @Bean

@Configuration标记一个类为配置类,替代 XML 文件。@Bean标记方法,把返回值注册为 Bean。

@ConfigurationpublicclassAppConfig{@BeanpublicDataSourcedataSource(){HikariDataSourceds=newHikariDataSource();ds.setJdbcUrl("jdbc:mysql://localhost:3306/mydb");returnds;}@BeanpublicJdbcTemplatejdbcTemplate(DataSourcedataSource){returnnewJdbcTemplate(dataSource);}}

@Configuration类会被 CGLIB 代理,@Bean方法之间互相调用返回容器中的单例。@Component不会被代理,方法间调用直接执行方法体。

3. 组件扫描

@Configuration@ComponentScan("com.example")publicclassAppConfig{}

@SpringBootApplication已经包含了@ComponentScan,默认扫描启动类所在包及其子包。

4. 依赖注入

@ServicepublicclassUserService{privatefinalUserDaouserDao;privatefinalEmailServiceemailService;publicUserService(UserDaouserDao,EmailServiceemailService){this.userDao=userDao;this.emailService=emailService;}}

构造器注入是 Spring 官方推荐的方式。类只有一个构造方法时,@Autowired可以省略。

5. 配置值注入

@ComponentpublicclassAppConfig{@Value("${app.name}")privateStringappName;@Value("${app.timeout:30}")privateinttimeout;}

或者用@ConfigurationProperties批量绑定:

@Component@ConfigurationProperties(prefix="app")@Getter@SetterpublicclassAppProperties{privateStringname;privateinttimeout;privateList<String>servers;}

四、配置类详解

1. @Configuration 的本质

@Configuration本身被@Component标注,所以它也是一个 Bean。但 Spring 对@Configuration类做了特殊处理——通过 CGLIB 生成子类,拦截@Bean方法的调用。

@ConfigurationpublicclassAppConfig{@BeanpublicUserDaouserDao(){returnnewUserDao();}@BeanpublicUserServiceuserService(){// 由于 CGLIB 代理,userDao() 返回容器中的单例returnnewUserService(userDao());}}

如果换成@Component,userDao()每次调用都会执行方法体,创建新实例。

2. @Bean 方法参数注入

@BeanpublicJdbcTemplatejdbcTemplate(DataSourcedataSource){returnnewJdbcTemplate(dataSource);}

Spring 会自动从容器中查找DataSource类型的 Bean 注入到方法参数。

3. @Bean 的生命周期回调

@Bean(initMethod="init",destroyMethod="cleanup")publicMyBeanmyBean(){returnnewMyBean();}

也可以在 Bean 类中用@PostConstruct和@PreDestroy。

4. 条件化配置

@ConfigurationpublicclassAppConfig{@Bean@ConditionalOnMissingBeanpublicObjectMapperobjectMapper(){returnnewObjectMapper();}@Bean@ConditionalOnProperty(name="app.cache.enabled",havingValue="true")publicCacheManagercacheManager(){returnnewCaffeineCacheManager();}}

5. 环境化配置

@Configuration@Profile("dev")publicclassDevConfig{@BeanpublicDataSourcedevDataSource(){...}}@Configuration@Profile("prod")publicclassProdConfig{@BeanpublicDataSourceprodDataSource(){...}}

五、AOP 全注解

1. 开启 AOP

@Configuration@EnableAspectJAutoProxypublicclassAopConfig{}

Spring Boot 中引入spring-boot-starter-aop后自动生效。

2. 定义切面

@Aspect@ComponentpublicclassLoggingAspect{@Pointcut("execution(* com.example.service.*.*(..))")publicvoidserviceLayer(){}@Around("serviceLayer()")publicObjectaround(ProceedingJoinPointpjp)throwsThrowable{longstart=System.currentTimeMillis();Objectresult=pjp.proceed();longcost=System.currentTimeMillis()-start;System.out.println(pjp.getSignature().getName()+" 耗时:"+cost+"ms");returnresult;}}

五种通知注解:@Before、@After、@AfterReturning、@AfterThrowing、@Around。

3. 自定义注解 + AOP

@Target(ElementType.METHOD)@Retention(RetentionPolicy.RUNTIME)public@interfaceLog{Stringvalue()default"";}@Aspect@ComponentpublicclassLogAspect{@Around("@annotation(log)")publicObjectlog(ProceedingJoinPointpjp,Loglog)throwsThrowable{System.out.println("执行:"+log.value());returnpjp.proceed();}}

六、事务全注解

@Configuration@EnableTransactionManagementpublicclassTransactionConfig{@BeanpublicPlatformTransactionManagertransactionManager(DataSourcedataSource){returnnewDataSourceTransactionManager(dataSource);}}

业务方法上使用@Transactional:

@ServicepublicclassOrderService{@Transactional(rollbackFor=Exception.class,timeout=30)publicvoidcreateOrder(Orderorder){orderDao.save(order);inventoryDao.decrease(order.getProductId(),order.getQuantity());}}

Spring Boot 中DataSourceTransactionManager自动配置,不需要手动声明。

七、Web 层全注解

1. 传统 Spring MVC 配置

XML 时代需要web.xml+spring-mvc.xml。全注解方式用WebApplicationInitializer替代web.xml:

publicclassWebAppInitializerimplementsWebApplicationInitializer{@OverridepublicvoidonStartup(ServletContextservletContext){// 创建 Spring 根容器AnnotationConfigWebApplicationContextrootContext=newAnnotationConfigWebApplicationContext();rootContext.register(AppConfig.class);// 创建 Spring MVC 容器AnnotationConfigWebApplicationContextwebContext=newAnnotationConfigWebApplicationContext();webContext.register(WebConfig.class);// 注册 DispatcherServletServletRegistration.Dynamicdispatcher=servletContext.addServlet("dispatcher",newDispatcherServlet(webContext));dispatcher.setLoadOnStartup(1);dispatcher.addMapping("/");}}

2. WebMvcConfigurer

替代spring-mvc.xml:

@Configuration@EnableWebMvc@ComponentScan("com.example.controller")publicclassWebConfigimplementsWebMvcConfigurer{@OverridepublicvoidaddInterceptors(InterceptorRegistryregistry){registry.addInterceptor(newLoginInterceptor()).addPathPatterns("/**").excludePathPatterns("/login","/register");}@OverridepublicvoidaddResourceHandlers(ResourceHandlerRegistryregistry){registry.addResourceHandler("/static/**").addResourceLocations("classpath:/static/");}@OverridepublicvoidconfigureMessageConverters(List<HttpMessageConverter<?>>converters){converters.add(newMappingJackson2HttpMessageConverter());}}

3. 控制器

@RestController@RequestMapping("/api/users")publicclassUserController{@AutowiredprivateUserServiceuserService;@GetMapping("/{id}")publicUsergetUser(@PathVariableLongid){returnuserService.getById(id);}@PostMappingpublicUsercreate(@RequestBody@ValidUseruser){returnuserService.save(user);}}

4. 全局异常处理

@RestControllerAdvicepublicclassGlobalExceptionHandler{@ExceptionHandler(BusinessException.class)publicResponseEntity<ErrorResponse>handleBusiness(BusinessExceptione){returnResponseEntity.badRequest().body(newErrorResponse(e.getMessage()));}@ExceptionHandler(Exception.class)publicResponseEntity<ErrorResponse>handleException(Exceptione){returnResponseEntity.status(500).body(newErrorResponse("服务器内部错误"));}}

八、全注解项目结构

src/main/java/com/example/ ├── config/ │ ├── AppConfig.java # 根配置 │ ├── WebConfig.java # Web 配置 │ ├── AopConfig.java # AOP 配置 │ └── TransactionConfig.java # 事务配置 ├── controller/ │ └── UserController.java ├── service/ │ ├── UserService.java │ └── impl/ │ └── UserServiceImpl.java ├── dao/ │ └── UserDao.java ├── entity/ │ └── User.java └── WebAppInitializer.java # 替代 web.xml

九、全注解 vs XML

对比维度全注解XML
配置位置代码内独立文件
可读性类与配置合一配置集中但分离
修改成本需重新编译改 XML 即可
类型安全编译期检查运行时才发现错误
重构支持IDE 自动重构手动修改
适用场景业务类、Controller、Service第三方类、动态配置
现代趋势主流逐步淘汰

混合使用:自己写的类用注解,第三方类用@Bean方法或 XML。全注解不等于完全不用 XML,而是以注解为主。

十、常见问题

1. @Configuration 与 @Component 混用

@Configuration类会被 CGLIB 代理,@Bean方法间调用返回单例。@Component不会被代理,方法间调用创建新实例。配置类一律用@Configuration。

2. @Bean 方法返回类型与注入类型不匹配

@BeanpublicDataSourcedataSource(){returnnewHikariDataSource();// 返回 HikariDataSource,注册为 DataSource 类型}

注入时按DataSource类型查找可以找到,按HikariDataSource查找也可以(Spring 会判断实际类型)。

3. 组件扫描范围

@ComponentScan默认扫描当前类所在包及其子包。启动类放在根包下,确保所有组件都在扫描范围内。

4. 循环依赖

构造器注入的循环依赖无法解决,启动报BeanCurrentlyInCreationException。字段注入可以通过三级缓存解决,但应通过重构消除循环依赖。

5. @EnableWebMvc 与 Spring Boot

Spring Boot 中不要手动加@EnableWebMvc,它会关闭 Spring Boot 的 Web 自动配置。需要自定义 Web 配置时,实现WebMvcConfigurer接口即可。

十一、总结

分类核心注解
声明 Bean@Component、@Service、@Repository、@Controller、@RestController
配置类@Configuration、@Bean、@ComponentScan、@Import
依赖注入@Autowired、@Qualifier、@Resource、@Value
配置绑定@ConfigurationProperties、@PropertySource
条件化@Conditional、@ConditionalOnXxx、@Profile
AOP@Aspect、@Pointcut、@Before、@Around
事务@EnableTransactionManagement、@Transactional
Web@EnableWebMvc、WebMvcConfigurer、@RestControllerAdvice
测试@SpringBootTest、@MockBean

全注解开发是 Spring 现代开发的主流方式。它把配置从 XML 转移到 Java 类和注解上,让代码和配置合一,类型安全,重构友好。Spring Boot 在此基础上进一步简化,通过自动配置和 Starter 机制,让开发者几乎不需要写配置类。理解全注解开发,是掌握 Spring Boot 自动配置原理的基础。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询