【Spring Framework】使用完全注解方式开发

Spring Framework 是一个非常灵活且强大的 Java 企业级开发框架,它允许开发人员以多种方式进行配置和开发。在现代 Java 开发中,使用完全注解的方式来进行配置和开发已经成为趋势,这种方式能够减少 XML 配置文件的使用,使代码更加简洁和易于维护。

在本文中,我将详细介绍如何使用 Spring 的注解配置来进行完全注解化开发,包括如何定义 Bean、管理依赖注入、配置数据库、实现 AOP、处理事务等方面。

1. 完全注解配置的优点

完全注解配置有许多优点:

  • 减少 XML 依赖:不再需要繁琐的 XML 配置文件,所有配置都可以在 Java 类中通过注解完成。
  • 提高可读性和可维护性:配置更加紧凑,易于阅读和维护。
  • 类型安全:利用 Java 类型系统进行配置,减少配置错误。
  • 更好的 IDE 支持:IDE 对注解提供了良好的自动补全和重构支持。
  • 便于测试:配置类可以通过单元测试进行独立验证。

2. 基本注解和概念

在 Spring 中,注解可以用来定义和配置 Bean,以及实现自动装配、事务管理等功能。以下是一些常用的注解:

  • @Configuration:用于定义配置类,该类可以替代 XML 配置文件。
  • @Bean:用于定义 Bean,返回的对象会被注册为 Spring 应用上下文中的一个 Bean。
  • @Component@Service@Repository@Controller:用于自动扫描并注册为 Spring Bean,分别用于不同层次的组件(通用组件、服务层、持久层和控制层)。
  • @Autowired:用于自动装配 Bean,可以作用于字段、构造器或方法上。
  • @Qualifier:与 @Autowired 一起使用,用于明确指定注入的 Bean。
  • @Value:用于注入属性值。
  • @PropertySource:指定外部属性文件的位置。
  • @EnableTransactionManagement:启用注解驱动的事务管理。
  • @Transactional:用于标记事务边界。
  • @EnableAspectJAutoProxy:启用基于注解的 AOP 支持。

3. 创建一个简单的 Spring 项目

为了演示完全注解化配置开发,我们将创建一个简单的 Spring 项目,包括以下几个模块:

  1. 配置类。
  2. 数据库连接和数据访问层。
  3. 服务层。
  4. 控制器层。
  5. AOP 和事务管理。

3.1 项目结构

src/main/java
|-- com.example|-- config|-- AppConfig.java|-- DataSourceConfig.java|-- WebConfig.java|-- model|-- User.java|-- repository|-- UserRepository.java|-- UserRepositoryImpl.java|-- service|-- UserService.java|-- UserServiceImpl.java|-- controller|-- UserController.java|-- aop|-- LoggingAspect.java|-- Application.java

3.2 配置类

3.2.1 AppConfig.java

AppConfig 是主配置类,启用组件扫描和其他核心功能。

package com.example.config;import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
import org.springframework.context.annotation.PropertySource;
import org.springframework.transaction.annotation.EnableTransactionManagement;@Configuration
@ComponentScan(basePackages = "com.example") // 扫描com.example包下的所有组件
@EnableTransactionManagement // 启用事务管理
@EnableAspectJAutoProxy // 启用AOP代理
@PropertySource("classpath:application.properties") // 加载属性文件
public class AppConfig {// AppConfig 是项目的核心配置类,不包含具体的 Bean 定义
}
3.2.2 DataSourceConfig.java

DataSourceConfig 用于配置数据源和 JdbcTemplate。

package com.example.config;import org.apache.commons.dbcp2.BasicDataSource;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.transaction.PlatformTransactionManager;import javax.sql.DataSource;@Configuration
public class DataSourceConfig {@Beanpublic DataSource dataSource() {BasicDataSource dataSource = new BasicDataSource();dataSource.setDriverClassName("com.mysql.cj.jdbc.Driver");dataSource.setUrl("jdbc:mysql://localhost:3306/mydatabase?useSSL=false&serverTimezone=UTC");dataSource.setUsername("root");dataSource.setPassword("password");// 可选配置dataSource.setInitialSize(5);dataSource.setMaxTotal(10);dataSource.setMaxIdle(5);dataSource.setMinIdle(2);return dataSource;}@Beanpublic JdbcTemplate jdbcTemplate(DataSource dataSource) {return new JdbcTemplate(dataSource);}@Beanpublic PlatformTransactionManager transactionManager(DataSource dataSource) {return new DataSourceTransactionManager(dataSource);}
}
3.2.3 WebConfig.java

如果你正在使用 Spring MVC,则可以使用 WebConfig 来配置 DispatcherServlet、视图解析器等。

package com.example.config;import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.ViewResolverRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import org.springframework.web.servlet.view.InternalResourceViewResolver;@Configuration
@EnableWebMvc // 启用Spring MVC
public class WebConfig implements WebMvcConfigurer {@Overridepublic void configureViewResolvers(ViewResolverRegistry registry) {InternalResourceViewResolver resolver = new InternalResourceViewResolver();resolver.setPrefix("/WEB-INF/views/");resolver.setSuffix(".jsp");registry.viewResolver(resolver);}// 可以在这里添加更多的 MVC 配置
}

3.3 模型类

创建一个简单的 User 模型类。

package com.example.model;public class User {private int id;private String name;private String email;// 构造函数public User() {}public User(int id, String name, String email) {this.id = id;this.name = name;this.email = email;}// Getter 和 Setterpublic int getId() {return id;}public void setId(int id) {this.id = id;}public String getName() {return name;}public void setName(String name) {this.name = name;}public String getEmail() {return email;}public void setEmail(String email) {this.email = email;}@Overridepublic String toString() {return "User{" +"id=" + id +", name='" + name + '\'' +", email='" + email + '\'' +'}';}
}

3.4 数据访问层

创建 UserRepository 接口和 UserRepositoryImpl 实现类,使用 JdbcTemplate 进行数据库操作。

3.4.1 UserRepository.java
package com.example.repository;import com.example.model.User;
import java.util.List;public interface UserRepository {void insertUser(User user);void updateUser(User user);void deleteUser(int id);User findUserById(int id);List<User> findAllUsers();
}
3.4.2 UserRepositoryImpl.java
package com.example.repository;import com.example.model.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Repository;import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.List;@Repository
public class UserRepositoryImpl implements UserRepository {@Autowiredprivate JdbcTemplate jdbcTemplate;@Overridepublic void insertUser(User user) {String sql = "INSERT INTO users (name, email) VALUES (?, ?)";jdbcTemplate.update(sql, user.getName(), user.getEmail());}@Overridepublic void updateUser(User user) {String sql = "UPDATE users SET name = ?, email = ? WHERE id = ?";jdbcTemplate.update(sql, user.getName(), user.getEmail(), user.getId());}@Overridepublic void deleteUser(int id) {String sql = "DELETE FROM users WHERE id = ?";jdbcTemplate.update(sql, id);}@Overridepublic User findUserById(int id) {String sql = "SELECT * FROM users WHERE id = ?";return jdbcTemplate.queryForObject(sql, new Object[]{id}, this::mapRowToUser);}@Overridepublic List<User> findAllUsers() {String sql = "SELECT * FROM users";return jdbcTemplate.query(sql, this::mapRowToUser);}private User mapRowToUser(ResultSet rs, int rowNum) throws SQLException {return new User(rs.getInt("id"),rs.getString("name"),rs.getString("email"));}
}

3.5 服务层

创建 UserService 接口和 UserServiceImpl 实现类,使用注解配置事务管理。

3.5.1 UserService.java
package com.example.service;import com.example.model.User;import java.util.List;public interface UserService {void registerUser(User user);void modifyUser(User user);void removeUser(int id);User getUserById(int id);List<User> listAllUsers();
}
3.5.2 UserServiceImpl.java
package com.example.service;import com.example.model.User;
import com.example.repository.UserRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;import java.util.List;@Service
public class UserServiceImpl implements UserService {@Autowiredprivate UserRepository userRepository;@Override@Transactionalpublic void registerUser(User user) {userRepository.insertUser(user);}@Override@Transactionalpublic void modifyUser(User user) {userRepository.updateUser(user);}@Override@Transactionalpublic void removeUser(int id) {userRepository.deleteUser(id);}@Overridepublic User getUserById(int id) {return userRepository.findUserById(id);}@Overridepublic List<User> listAllUsers() {return userRepository.findAllUsers();}
}

3.6 控制器层

在控制器层中使用 @Controller 注解定义 Web 控制器。这里,我们将创建一个简单的控制器来展示如何处理请求。

3.6.1 UserController.java
package com.example.controller;import com.example.model.User;
import com.example.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.*;import java.util.List;@Controller
@RequestMapping("/users")
public class UserController {@Autowiredprivate UserService userService;@GetMappingpublic String listUsers(Model model) {List<User> users = userService.listAllUsers();model.addAttribute("users", users);return "user/list"; // 视图名称}@GetMapping("/{id}")public String getUser(@PathVariable int id, Model model) {User user = userService.getUserById(id);model.addAttribute("user", user);return "user/detail";}@PostMappingpublic String createUser(@ModelAttribute User user) {userService.registerUser(user);return "redirect:/users";}@PutMapping("/{id}")public String updateUser(@PathVariable int id, @ModelAttribute User user) {user.setId(id);userService.modifyUser(user);return "redirect:/users/" + id;}@DeleteMapping("/{id}")public String deleteUser(@PathVariable int id) {userService.removeUser(id);return "redirect:/users";}
}

3.7 AOP 切面编程

在 Spring 中,AOP(Aspect-Oriented Programming)允许我们将横切关注点(如日志记录、事务管理、权限检查等)从业务逻辑中分离出来。这里,我们将创建一个简单的日志切面。

3.7.1 LoggingAspect.java
package com.example.aop;import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;@Aspect
@Component
public class LoggingAspect {private static final Logger logger = LoggerFactory.getLogger(LoggingAspect.class);@Before("execution(* com.example.service.UserService.*(..))")public void logBefore(JoinPoint joinPoint) {logger.info("执行方法: " + joinPoint.getSignature().getName());}@AfterReturning(pointcut = "execution(* com.example.service.UserService.*(..))", returning = "result")public void logAfterReturning(JoinPoint joinPoint, Object result) {logger.info("方法返回: " + joinPoint.getSignature().getName() + ",返回值: " + result);}
}

3.8 启动类

最后,创建一个启动类来运行 Spring 应用程序。

3.8.1 Application.java
package com.example;import com.example.config.AppConfig;
import com.example.service.UserService;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;public class Application {public static void main(String[] args) {AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);UserService userService = context.getBean(UserService.class);// 添加用户userService.registerUser(new User(1, "Alice", "alice@example.com"));// 列出所有用户userService.listAllUsers().forEach(System.out::println);// 查找用户User user = userService.getUserById(1);System.out.println("查找到的用户: " + user);// 更新用户user.setName("Alice Updated");userService.modifyUser(user);// 删除用户userService.removeUser(1);context.close();}
}

4. 总结

本文介绍了如何使用 Spring 完全注解化的方式来进行开发。通过使用注解,我们可以减少 XML 配置文件的使用,使项目的配置更加直观和简洁。以下是本文的主要内容:

  • 配置类:使用 @Configuration@Bean@ComponentScan 等注解定义配置类。
  • 数据库配置:使用 DataSourceJdbcTemplate 以及 @Autowired 自动装配数据源。
  • 服务层和控制器层:使用 @Service@Controller 注解定义业务逻辑和控制器,并使用 @Autowired 注入依赖。
  • AOP 和事务管理:通过 @Aspect@Transactional 注解实现日志记录和事务管理。

这种完全注解化的开发方式在 Spring Boot 中得到了进一步的增强和推广,成为现代 Java 开发的主流方式。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/387383.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

thinkPHP开发的彩漂网站源码,含pc端和手机端

源码简介 后台thinkPHP架构,页面程序双分离,Mysql数据库严谨数据结构、多重数据审核机制、出票机制和监控机制,html5前端技术适用移动端,后台逻辑更多以server接口可快捷实现对接pc和ap,下载会有少量图片素材丢失,附件有下载说明前端demo账户密码和后台管理地址管理员账户密码…

C 语言动态链表

线性结构->顺序存储->动态链表 一、理论部分 从起源中理解事物&#xff0c;就是从本质上理解事物。 -杜勒鲁奇 动态链表是通过结点&#xff08;Node&#xff09;的集合来非连续地存储数据&#xff0c;结点之间通过指针相互连接。 动态链表本身就是一种动态分配内存的…

Java 8-函数式接口

目录 一、概述 二、 函数式接口作为方法的参数 三、函数式接口作为方法的返回值 四、 常用的函数式接口 简单总结 简单示例 4.1 Consumer接口 简单案例 自我练习 实际应用场景 多线程处理 4.2 Supplier接口 简单案例 自我练习 实际应用场景 配置管理 4.3 Func…

TypeError: Components is not a function

Vue中按需引入Element-plus时&#xff0c;报错TypeError: Components is not a function。 1、参考Element-plus官方文档 安装unplugin-vue-components 和 unplugin-auto-import这两款插件 2、然后需要在vue.config.js中配置webPack打包plugin配置 3、重新启动项目会报错 T…

Java----反射

什么是反射&#xff1f; 反射就是允许对成员变量、成员方法和构造方法的信息进行编程访问。换句话来讲&#xff0c;就是通过反射&#xff0c;我们可以在不需要创建其对象的情况下就可以获取其定义的各种属性值以及方法。常见的应用就是IDEA中的提示功能&#xff0c;当我…

鸿蒙(HarmonyOS)自定义Dialog实现时间选择控件

一、操作环境 操作系统: Windows 11 专业版、IDE:DevEco Studio 3.1.1 Release、SDK:HarmonyOS 3.1.0&#xff08;API 9&#xff09; 二、效果图 三、代码 SelectedDateDialog.ets文件/*** 时间选择*/ CustomDialog export struct SelectedDateDialog {State selectedDate:…

声学气膜馆的优势:卓越声学性能与多样化应用—轻空间

随着科技的发展和人们对音质要求的提高&#xff0c;声学气膜馆逐渐成为现代建筑中的重要组成部分。声学气膜馆不仅在设计和声学性能上有显著优势&#xff0c;还在提高场馆舒适度、增加活动多样性以及带来经济效益方面表现突出。 提升声学环境质量 声学气膜馆通过利用先进的声学…

未来GenAI 怎样逐步改变搜索?

欢迎来到雲闪世界。人工智能的进步正在将传统搜索引擎转变为应答机。这一转变是由网络搜索领域的新老参与者共同推动的&#xff0c;并正在影响世界各地人们获取信息的方式。 谁是基于 GenAI 的搜索的主要参与者&#xff1f;他们如何提出解决方案&#xff1f;这对用户有何影响&a…

18万就能买华为智驾车,你当不了韭菜!

文 | AUTO芯球 作者 | 雷慢 万万没想到啊&#xff0c; 把智能驾驶汽车价格打到最低的&#xff0c; 居然是智驾实力最强的华为&#xff0c; 这你敢信吗 就现在&#xff0c;17.99万就能买华为智驾的车了&#xff0c; 它就是长安和华为合作的首个车型&#xff0c; 深蓝S07…

【Spring Boot教程:从入门到精通】掌握Spring Boot开发技巧与窍门(三)-配置git环境和项目创建

主要介绍了如何创建一个Springboot项目以及运行Springboot项目访问内部的html页面&#xff01;&#xff01;&#xff01; 文章目录 前言 配置git环境 创建项目 ​编辑 在SpringBoot中解决跨域问题 配置Vue 安装Nodejs 安装vue/cli 启动vue自带的图形化项目管理界面 总结 前言 …

十日Python项目——第四日(用户中心—收货地址)

#前言&#xff1a; 在最近十天我会用Python做一个购物类项目&#xff0c;会用到DjangoMysqlRedisVue等。 今天是第四天&#xff0c;主要负责撰写用户中心部分的收货地址部分。若是有不懂大家可以先阅读我的前三篇博客以能够顺承。 若是大家基础有不懂的&#xff0c;小编前面…

01、爬虫学习入门

爬虫&#xff1a;通过编写程序&#xff0c;来获取获取互联网上的资源 需求&#xff1a;用程序模拟浏览器&#xff0c;输入一个网址&#xff0c;从该网址获取到资源或内容 一、入门程序 #使用urlopen来进行爬取 from urllib.request import urlopen url "http://www.ba…

我们的网站被狗爬了!

大家好&#xff0c;我是程序员鱼皮。 世风日下&#xff0c;人心不古。我们的程序员面试刷题网站 《面试鸭》 才刚刚上线了一个多月&#xff0c;就由于过于火爆&#xff0c;被不少同行和小人发起网络攻击。 而且因为我们已经有 4500 多道人工整理的企业高频面试题、100 多个各…

【JavaScript】函数的动态传参

Javacript&#xff08;简称“JS”&#xff09;是一种具有函数优先的轻量级&#xff0c;解释型或即时编译型的编程语言。虽然它是作为开发Web页面的脚本语言而出名&#xff0c;但是它也被用到了很多非浏览器环境中&#xff0c;JavaScript基于原型编程、多范式的动态脚本语言&…

第六周:机器学习周报

机器学习周报 摘要Abstract机器学习——类神经网络训练不起来怎么办&#xff1f;1. 自动调整学习率&#xff08;learning rate&#xff09;1.1 特制化的Learning Rate——parameter dependent1.1.1 Root Mean Square&#xff08;RMS&#xff0c;均方根&#xff09;1.1.2 RMSPro…

Qt Creator使用git管理代码

1.在GitHub中新建仓库&#xff0c;设置好仓库名后&#xff0c;其它的设置默认即可。 2.打开git bash&#xff0c;输入以下命令&#xff1a; git config --global user.name "xxxxx" #设置你的GitHub用户名 git config --global user.email "xxxxxxxxx.…

DMB,DSB,ISB三个指令区别

此部分说明三个指令的具体区别&#xff08;在指令流水线上说明&#xff09;&#xff0c;这三个指令主要目的在于确保程序在多处理器环境下的稳定性和一致性&#xff0c;避免由于指令乱序和内存操作重排引起的不可预测行为 一个简化的流水线&#xff0c;包含以下阶段&#xff1…

[Docker][Docker Registry]详细讲解

目录 1.什么是Docker Registry&#xff1f;2.镜像源配置3.镜像仓库命令1.命令清单2.docker login2.docker pull3.docker push4.docker search5.docker logout 1.什么是Docker Registry&#xff1f; 镜像仓库(Docker Registry) 功能&#xff1a;负责存储、管理和分发镜像&#x…

腾讯云网站/域名备案操作流程

目录 一、备案服务授权二、备案 一、备案服务授权 二、备案 在“我的备案”页面&#xff0c;点击【去备案】&#xff1a; 点击【新增备案】&#xff1a; 点击【同意并继续】&#xff1a; 选择省份&#xff0c;点击【开始备案】&#xff1a; 输入备案相关信息后点击【提交】…

vue给数组对象赋值改变对象里面的数据,数据没有更新this.$set

替换数组startTime的值&#xff1a; 原数据 this.serviceTimeList.push({serviceTimeName: 服务时间段,startTime: this.startTime,endTime: this.endTime,currentDateStart: this.currentDate,currentDateEnd: this.currentDate}) this.$set(this.array, index, newValue); …